Remember to mark the functions you wish to export with
__declspec(dllexport). Also for these functions to be directly accessible to DBPro as a "command" you have to add string table entries that matches the DBPro function name to the name of your actually exported function.
The exported function name may be mangled and you need to take this into account when writing your string table entries.
The string table entries need to use an id value between 101 and 999 or the DBPro compiler won't read it and are written using the following layout:
Quote: "DBPRO FUNCTION NAME WHICH MAY CONTAIN SPACES BUT NO OTHER SPECIAL CHARACTERS[%XYZ%exportedFunctionName"
The opening square bracket is optional; if it is present it indicates that the function will return a value. If it does then the first data type specifier in the XYZ list is the return type of the function. A function that doesn't return anything and doesn't have any arguments specify a single zero between the two % signs.
The XYZ part consists of one or more letters which indicate the data type of the argument in order (or as stated above, if a return value is provided by the function, that one's data type letter comes first).
There are a number of valid specifiers and some of them actually require a certain argument layout of your function, such as the ones taking an array pointer. However the standard, "normal" ones are as follows:
○ L - 32-bit signed integer
○ D - 32-bit unsigned integer; this is used for BYTE, WORD and DWORD alike which are all really 32-bit values (or castable from and to it) as far as DBPro is concerned
○ F - 32-bit floating point value. If returning a float, the actual C++ function should return the float's bit pattern interpreted as a DWORD.
○ S - Zero-terminated string. Proper DBPro string handling requires using the CreateDeleteString function that is pointed to by the Globstruct that you can receive a pointer to through the startup procedure TheComet hinted at. This function is called to let the DBP engine delete and/or allocate string memory; if you don't do this any previous DBPro strings won't be deleted and you'll thus end up with memory leaks.
○ R - 64-bit integer (double integer)
○ O - 64-bit floating point value (double float)
The startup / shutdown routine made available by DBPro is as follows:
void __cdecl Constructor(void) is called after your plugin has been loaded "for use".
You can use the DLLMain entry point for setup, but beware that this is in fact called twice when loading the plugin during compilation for validating the presence of function calls inside it. As such it is probably not desireable to do any hefty setup routine from there.
void __cdecl ReceiveCoreDataPtr(void *pCore) is called next and will give you the globstruct pointer as described above. Include the "Globstruct.h" header file from DarkSDK and cast the void pointer to
sGlobstruct* and store it in a globally accessible pointer variable if you need it (chances are you will, if you for example need to return strings).
void __cdecl PreDestructor(void) is called during shutdown of your program.
I believe it is called before any of the dll's are actually unloaded so that you can do any cleanup operations that require access to other loaded dll's.
void __cdecl Destructor(void) is called prior to unloading your dll and can be used to contain cleanup logic (free dynamically allocated memory etc.).
If you don't need any of these callbacks you can just omit writing / exporting those functions, they're not mandatory.
Also, the PreDestructor / Destructor functions are NOT called if the DBPro program crashes, so I tend to use the DLLPROCESS_DETACH reason invocation of DLLMain to do the actual cleanup. This is called automatically by Windows and will be called even in the case of a crash. You cannot be sure in what order the dll's are unloaded though, so if you need guaranteed access to those the PreDestructor should be used, but with emergency cleanup done from DLLMain if found necessary. Of course modern OS'es (such as probably any Windows version DBPro programs will run on) will restore memory after a crash anyway so you might argue that this part is rather unnecessary.
Finally, as Hotline said, you should show us your compilation errors if those occur. Chances are there are linker errors due to missing (or no) libraries being included.
"Why do programmers get Halloween and Christmas mixed up?" Because Oct(31) = Dec(25)