-
Notifications
You must be signed in to change notification settings - Fork 7
Tutorial: Setting up the ACEs
<< Tutorials | Creating the JSON >>
As with most extensions, the Actions, Conditions, and Expressions make up most of your extension. In EDIF, they are placed within the scope of the Extension class, so they have access to any data members and member functions you define in it. Before you start designing your A/C/Es, you need to be aware of what kind of parameters are available to you and how they affect each A/C/E.
As a general rule of thumb, all parameters and return types will be 4 bytes in size. This means int/long, float, and any kind of pointer. This is also a core reason why double precision floats cannot be used: they are 8 bytes instead of 4. For efficiency and convenience purposes, Yves and Francois opted not to pass around pointer to doubles and instead pass around floats. In fact, this 4-byte rule applies to the entire MMF2 SDK - but only for parameters and return types!
More in-depth parameter explanation is in Tutorial: Creating the JSON; for now we will discuss how to create A/C/Es with strings, integers, and floats.
For starters, you need to open Extension.hpp, Extension.cpp, Actions.cpp, Conditions.cpp, and Expressions.cpp - you will, of course, need all five open.
There's no specific way to say that a particular function is an Action, Condition, or Expression when you declare/define them, but you can usually tell at a glance from the return types (usually). Actions don't return anything (void is the return type), conditions usually return a bool, and an expressions return an integer, float or c-string (const TCHAR *). And that's another thing to note - the things return from expressions are generally the parameters A/C/Es will receive - that is, integers, single-precision floats, and C-style strings.
To create an A/C/E, scroll down Extension.hpp - the example ones should stand out to you. Here you have a sort of planning area - set up your A/C/Es like normal functions keeping in mind the parameter and return type limitations. You should write parameter names even though you don't have to - it will make planning easier. Once you've planned them out, you'll need to visit each of Actions.cpp, Conditions.cpp, and Expressions.cpp to write the implementations. The reason the A/C/Es are kept in separate files is for organizational purposes - if it so pleases you, you can define them all in the same files, but it is not recommended. Remember that you have to write the return type and Extension:: before the name of the function, and re-write the parameter list and parameter names. You can then define it like a normal function, but since you're in the scope of your class and the A/C/Es are instance member functions, you have access to the instance data members in your Extension class. You don't have to write this-> unless you prefer that coding style or you need to get around variable scope shadowing (e.g. if you have a parameter with the same name, which is a bad idea anyway).
Once you start setting up the A/C/Es like this you may notice you made some easrly design mistake and you may have changed the signatures of the A/C/Es - remember you also have to change the signatures in the Extension class too. The parameter names don't have to match, but you should make sure they do to avoid confusion later on. Once you've gotten everything set up, pay a visit to Extension.cpp - here you will need to actually link the A/C/Es to IDs your Extension class' constructor. These will correspond to the IDs in the JSON, so make sure everything matches up. IDs must start at 0 and you cannot skip IDs. Once you've assigned IDs and you release a version of your extension, you should consider those IDs permanent - changing them could mess up existing MFAs that people have made with older versions of your extension. You'll also need to know these IDs if you plan to port your extension to another runtime.
That's most of what you'll need to know for the basics of setting up the A/C/Es - next, you should read about Creating the JSON, which explains all the supported parameter types and how they affect the signature of your A/C/Es.
Extension.hpp:
//Actions - Defined in Actions.cpp
void ActionExample(int ExampleParameter);
void SecondActionExample();
//Conditions - Defined in Conditions.cpp
bool AreTwoNumbersEqual(int FirstNumber, int SecondNumber);
//Expressions - Defined in Expressions.cpp
int Add(int FirstNumber, int SecondNumber);
const TCHAR * HelloWorld();
Actions.cpp:
void Extension::ActionExample(int ExampleParameter)
{
}
void Extension::SecondActionExample()
{
}
bool Extension::AreTwoNumbersEqual(int First, int Second)
{
return First == Second;
}
int Extension::Add(int First, int Second)
{
return First + Second;
}
const TCHAR *Extension::HelloWorld()
{
return _T("Hello world!");
//return Runtime.CopyString(MyString.c_str()); //for stdtstrings
}
typedef std::basic_string<TCHAR> stdtstring;
Extension.cpp: <constructor>
LinkAction(0, ActionExample);
LinkAction(1, SecondActionExample);
LinkCondition(0, AreTwoNumbersEqual);
LinkExpression(0, Add);
LinkExpression(1, HelloWorld);