Many applications written in high-level programming languages such as C# must interact with programs written in lower-level languages, such as C. The usual way this is done is to have the C code export a set of functions that can be called by the C# application. This allows function calls from C# to C, but there are many cases where function calls in the other direction (C to C#) are required. One way to do this is to use a C# unmanaged function pointer delegate. This is a C# type that can be passed into a C function as a function pointer. When the C code calls the function, it will run C# code.
The C# wrapper class needs a few declarations to make this work. The C code must define a setter function for setting the function pointer, and the C# wrapper needs a declaration of this function. The C# wrapper also needs to declare a delegate type that matches the callback function’s C prototype. That delegate type must be declared as an unmanaged function pointer with an appropriate calling convention. The C# wrapper should also have a variable with the delegate’s type. A C# function is assigned to the variable as its value. After this, the variable can be passed to the C setter function so the C# function can be called from C code.
The following code example shows all of the declarations needed to call a C# function from native C code:
/* C# wrapper class for native C code */ public class CSWrapper {
/* Declaration for the delegate type */ [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate int cs_delegate_for_c_function_t(String arg1, int arg2);
/* Declaraction of the C setter function */ [DllImport(“library”, EntryPoint = “native_set_callback”)] static extern void native_set_callback(cs_delegate_for_c_function_t cb);
/* Variable of delegate type */ private cs_delegate_for_c_function_t CSDelegatePointer;
/* C# function to be called by C code */ private static int CSFunctionToCall(String arg1, int arg2) { Console.Write(“Hello, I was called by native C code.”); }
/* Function to set the C callback */ public void Init() { /* NOTE: If we don’t keep a pointer, our delegate might be * garbage collected. */ CSDelegatePointer = CSFunctionToCall; native_set_callback(CSDelegatePointer); } };
|