Complete Communications Engineering

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);

    }

};