Uncovering the Hidden DLL Function Callback Feature
I took a little break today and dropped-in on the REBOL3 AltME world to find an interesting question being asked by Cyphre and a few other users: The word CALLBACK appears in the REBOL binary, but what does it do? Here is some little known information about this feature. Callbacks in DLL Functions (Routines)When using the External Library Interface (DLLs), you can pass a REBOL function to be called back from within a DLL function. REBOL will deal with the argument conversions in both directions, but you still have to write it with great care, because interfacing in this way to DLL code is tricky business. Example of a CallbackHere is an example written by Cyphre that helps show the way a callback function works. In REBOL you would write a routine (a DLL interface function) such as: test: make routine! [ a [int] b [int] c [callback [int int return: [int]]] return: [int] ] test-lib "test" Here the c argument is a callback function interface specification that takes two integers and returns an integer result. Note that the argument names are not provided, only their datatypes. Then, in the test.dll code you might write the something like: extern "C" MYDLL_API int test(int a, int b, int (*pFunc)(int, int)) { int result = pFunc(a, b); return result; } And finally, try it out, you would write the actual callback function such as: add-it: func [a b][return a + b] and give it a try with: >> test 1 2 :add-it == 3 Here the TEST routine is called and control is passed to its C DLL function along with a pointer to a special "trampoline" function (here the pointer is referenced with pFunc) that marshals the arguments and passes them to the callback function that is interpreted within REBOL. Special NotesThere are a few important notes to keep in mind:
I would like to thank Cyphre, Jaime Vargas, Romano, and Alphe Salas-Schuman for their help and participation in this project. Dynamic Allocation on Callbacks: CHAR-ARRAYThe CHAR-ARRAY word can be used in the place of CHAR* to make a copy of a C string that is being passed to REBOL. This allows the string to exist within REBOL's memory space and not be affected by changes that might occur in the C space (such as volatile reuse of memory). For example: dup: make routine! [ string [char*] action [callback [char-array 2000] return: [char*]] ] test-lib "dup" Each time the ACTION callback function is called (from C), its argument will be dynamically allocated as string of length 2000. If the C code provided a pointer to memory, the contents of that memory will be copied into the newly allocated memory. This will happen each time the callback function is invoked.
|
Updated 15-Jun-2024 - Copyright Carl Sassenrath - WWW.REBOL.COM - Edit - Blogger Source Code |