Difference between revisions of "Function Definition"
(New page: By default, the FM 7 API requires you to define each Function Definition in multiple files. This means duplication on Mac & Windows. It is possible to modify the main FMExample_Plugin.cpp ...) |
|||
| Line 24: | Line 24: | ||
Define each of our plugins details. | Define each of our plugins details. | ||
| − | For each Function Definition, I have created a set of definitions as below. The 'ID' as far as I can tell can be any number, but once you have set it for a function, you cannot change or else it will no longer link for any FileMaker database which calls that function. I have used increments of 10 so that I can insert a function at a later date if wanted. | + | For each Function Definition, I have created a set of definitions as below. The 'ID' as far as I can tell can be any number, but once you have set it for a function, you cannot change it or else it will no longer link for any FileMaker database which calls that function. I have used increments of 10 so that I can insert a function at a later date if wanted. |
| Line 107: | Line 107: | ||
Notice that our actual Function Definition is now a single line per definition. | Notice that our actual Function Definition is now a single line per definition. | ||
| + | |||
| + | |||
| + | |||
| + | ===Step Five=== | ||
| + | Update our Plugin Shutdown routine. Check that we are using the same ID's | ||
| + | |||
| + | /* ::=- Do_PluginShutdown =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=:: */ | ||
| + | static void Do_PluginShutdown(void) | ||
| + | { | ||
| + | // Unregister plug-in functions | ||
| + | fmx::QuadCharAutoPtr pluginID('I', 'D', 'M', 'A'); | ||
| + | fmx::errcode err; | ||
| + | |||
| + | err = fmx::ExprEnv::UnRegisterExternalFunction(*pluginID, IDMA_Version_ID ); | ||
| + | err = fmx::ExprEnv::UnRegisterExternalFunction(*pluginID, IDMA_DoScript_ID ); | ||
| + | |||
| + | // DeInitialise any variables as necessary | ||
| + | |||
| + | } // Do_PluginShutdown | ||
| + | |||
| + | |||
| + | |||
| + | ===Step Six=== | ||
| + | I also wanted to move my Plugin Option String, Name and Description out of the .string or .rc files. I added their #define's earlier in step one. Now, I need to get the plugin to use these instead. | ||
| + | |||
| + | |||
| + | *1st - Add the following two new functions | ||
| + | |||
| + | void copyCharToUnichar(char * S, FMX_Long maxLength, FMX_Unichar * R) | ||
| + | { // convert the 'char' string into a 'FMX_Unichar' string. Assumes NULL byte terminated string passed. | ||
| + | long i = 0; | ||
| + | |||
| + | while ( (i < (maxLength-2)) && (S[i] != 0) ) | ||
| + | { | ||
| + | R[i] = (FMX_Unichar)S[i]; | ||
| + | i++; | ||
| + | } | ||
| + | R[i] = 0x0000; // terminate with a NULL | ||
| + | |||
| + | } | ||
| + | |||
| + | |||
| + | void IDMA_GetString(unsigned long whichString, FMX_ULong /* winLangID */, FMX_Long resultsize, FMX_Unichar* string) | ||
| + | { // takes the requested 'whichString' and returns the appropriate response, converted to a UniChar with a NULL termination. | ||
| + | switch (whichString) | ||
| + | { | ||
| + | case kFMXT_OptionsStr: copyCharToUnichar(IDMA_Plugin_OptionString, resultsize, string); break; // the "IDMA1nnYYnn"; string | ||
| + | case kFMXT_NameStr: copyCharToUnichar(IDMA_Plugin_Name, resultsize, string); break; // the plugin name. eg. IDMA Plugin | ||
| + | case kFMXT_AppConfigStr: copyCharToUnichar(IDMA_Plugin_Description, resultsize, string); break; // the plugin description. eg. This plugin... | ||
| + | |||
| + | default: copyCharToUnichar("Error : Unknown Request" , resultsize, string); | ||
| + | }// switch (whichString) | ||
| + | |||
| + | } // IDMA_GetString (FMX_Unichar* version) | ||
| + | |||
| + | |||
| + | *2nd - Modify the FMExternCallProc(FMX_ExternCallPtr pb) function. | ||
| + | |||
| + | case kFMXT_GetString: | ||
| + | { | ||
| + | IDMA_GetString(gFMX_ExternCallPtr->parm1, gFMX_ExternCallPtr->parm2, gFMX_ExternCallPtr->parm3, reinterpret_cast<FMX_Unichar*>(gFMX_ExternCallPtr->result)); | ||
| + | } | ||
| + | break; | ||
Revision as of 22:18, 11 July 2007
By default, the FM 7 API requires you to define each Function Definition in multiple files. This means duplication on Mac & Windows. It is possible to modify the main FMExample_Plugin.cpp file to include the definitions all in the one file, removing the duplication.
In this example, I have replaced the use of the 'FMExample.strings' file (Mac) and 'FMExamplePlugin.rc' file (Windows) to define each Function.
Step One
Define the Plugin Option String, Name and Description fields.
#define IDMA_Plugin_Name "IDMA Plugin" #define IDMA_Plugin_Description "This plug-in provides additional functionality to FileMaker." #define IDMA_Plugin_OptionString "IDMA1nnYYnn" // ^--^ || | |---- // No Win32s support // | || |------ // Want idle time // | ||-------- // No old external functions // | |--------- // Has preferences dialog // |-------------- // 'IDMA' plug-in ID
Note : I just copied these from the .strings or .rc file, then appended the #define name to the start instead.
Step Two
Define each of our plugins details.
For each Function Definition, I have created a set of definitions as below. The 'ID' as far as I can tell can be any number, but once you have set it for a function, you cannot change it or else it will no longer link for any FileMaker database which calls that function. I have used increments of 10 so that I can insert a function at a later date if wanted.
// Function IDs ====WARNING : ID Values are important. Do not change once used, or will affect FileMaker linkage !!! === #define IDMA_Version_Name "Version( \"Version\" )" #define IDMA_Version_ID 201 #define IDMA_Version_Min 0 #define IDMA_Version_Max 1 #define IDMA_Version_Flags fmx::ExprEnv::kMayEvaluateOnServer | fmx::ExprEnv::kDisplayInAllDialogs #define IDMA_DoScript_Name "idma_DoScript( Get(FileName) ; scriptname ; paramater )" #define IDMA_DoScript_ID 211 #define IDMA_DoScript_Min 2 #define IDMA_DoScript_Max 3 #define IDMA_DoScript_Flags fmx::ExprEnv::kMayEvaluateOnServer | fmx::ExprEnv::kDisplayInAllDialogs
Repeat the above for each additional Function Definition.
Step Three
We need to create a couple of new functions to replicate the 'Do_GetString' function that comes with the API to read our define's instead.
static fmx::TextAutoPtr _n(char * S)
{ // return the function name only as a FMX::TextAutoPtr. eg. returns 'Version' from 'Version( \"Version\" )'
fmx::TextAutoPtr R;
R->Assign(S);
// The string for this whichStringID is a Function Prototype, but all the plug-in needs now is the Function Name by itself.
fmx::TextAutoPtr parenToken; parenToken->Assign("(");
unsigned long originalSize = R->GetSize();
unsigned long firstParenLocation;
firstParenLocation = R->Find(*parenToken, 0);
R->DeleteText(firstParenLocation, originalSize-firstParenLocation);
return R;
} // Do_GetString (TextAutoPtr version)
static fmx::TextAutoPtr _p(char * S)
{ // return the function definition as a FMX::TextAutoPtr. eg. returns 'Version( \"Version\" )'
fmx::TextAutoPtr R;
R->Assign(S);
return R;
} // Do_GetString (TextAutoPtr version)
Step Four
Modify the Do_Plugin_Inti() function as below
/* ::=- Do_PluginInit =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=:: */
static FMX_Long Do_PluginInit(FMX_Short version)
{
// Check the app API version
if ((version < k70ExtnVersion) || (version > kMaxExtnVersion))
{
// This version of FileMaker is not supported; let FileMaker disable this
// plug-in and report the problem to the user.
return (kBadExtnVersion);
}
// Initialise any variables as necessary.
// Register plug-in functions
fmx::QuadCharAutoPtr pluginID('I', 'D', 'M', 'A');
fmx::errcode err;
err = fmx::ExprEnv::RegisterExternalFunction(*pluginID, IDMA_Version_ID, *_n(IDMA_Version_Name), *_p(IDMA_Version_Name), IDMA_Version_Min, IDMA_Version_Max, IDMA_Version_Flags, Do_Version );
err = fmx::ExprEnv::RegisterExternalFunction(*pluginID, IDMA_DoScript_ID, *_n(IDMA_DoScript_Name), *_p(IDMA_DoScript_Name), IDMA_DoScript_Min, IDMA_DoScript_Max, IDMA_DoScript_Flags, Do_StartScript );
// Return kCurrentExtnVersion to enable the plug-in in FileMaker.
return (kCurrentExtnVersion);
} // Do_PluginInit
Notice that our actual Function Definition is now a single line per definition.
Step Five
Update our Plugin Shutdown routine. Check that we are using the same ID's
/* ::=- Do_PluginShutdown =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=:: */
static void Do_PluginShutdown(void)
{
// Unregister plug-in functions
fmx::QuadCharAutoPtr pluginID('I', 'D', 'M', 'A');
fmx::errcode err;
err = fmx::ExprEnv::UnRegisterExternalFunction(*pluginID, IDMA_Version_ID );
err = fmx::ExprEnv::UnRegisterExternalFunction(*pluginID, IDMA_DoScript_ID );
// DeInitialise any variables as necessary
} // Do_PluginShutdown
Step Six
I also wanted to move my Plugin Option String, Name and Description out of the .string or .rc files. I added their #define's earlier in step one. Now, I need to get the plugin to use these instead.
- 1st - Add the following two new functions
void copyCharToUnichar(char * S, FMX_Long maxLength, FMX_Unichar * R)
{ // convert the 'char' string into a 'FMX_Unichar' string. Assumes NULL byte terminated string passed.
long i = 0;
while ( (i < (maxLength-2)) && (S[i] != 0) )
{
R[i] = (FMX_Unichar)S[i];
i++;
}
R[i] = 0x0000; // terminate with a NULL
}
void IDMA_GetString(unsigned long whichString, FMX_ULong /* winLangID */, FMX_Long resultsize, FMX_Unichar* string)
{ // takes the requested 'whichString' and returns the appropriate response, converted to a UniChar with a NULL termination.
switch (whichString)
{
case kFMXT_OptionsStr: copyCharToUnichar(IDMA_Plugin_OptionString, resultsize, string); break; // the "IDMA1nnYYnn"; string
case kFMXT_NameStr: copyCharToUnichar(IDMA_Plugin_Name, resultsize, string); break; // the plugin name. eg. IDMA Plugin
case kFMXT_AppConfigStr: copyCharToUnichar(IDMA_Plugin_Description, resultsize, string); break; // the plugin description. eg. This plugin...
default: copyCharToUnichar("Error : Unknown Request" , resultsize, string);
}// switch (whichString)
} // IDMA_GetString (FMX_Unichar* version)
- 2nd - Modify the FMExternCallProc(FMX_ExternCallPtr pb) function.
case kFMXT_GetString:
{
IDMA_GetString(gFMX_ExternCallPtr->parm1, gFMX_ExternCallPtr->parm2, gFMX_ExternCallPtr->parm3, reinterpret_cast<FMX_Unichar*>(gFMX_ExternCallPtr->result));
}
break;