Call C function inside C# via function pointer

.net, c, c#

Solution

You'll want to use Marshal.GetDelegateForFunctionPointer. You won't even need to use unsafe code.

delegate void TestCallbackDelegate(); //must match the signature of test_callback()

public static void callCallback(int ptr)
{
    IntPtr nativePtr = new IntPtr( ptr );

    var callback = Marshal.GetDelegateForFunctionPointer<TestCallbackDelegate>( nativePtr );

    callback();
}

public static int test(string param)
{
    char[] ptrChar = param.ToCharArray();
    int ptrInt = 0;

    ptrInt = ( ((int)(0xFF00 & (int)ptrChar[1]) | (0x00FF & (int)ptrChar[1])) << 16 ) |
                (int)(0xFF00 & (int)ptrChar[0]) | (0x00FF & (int)ptrChar[0]);

    callCallback(ptrInt);
}

Although a much simpler way would be to just pass a `void*` to the C# method, and it will automatically get marshalled to `IntPtr`. Here's a minimal example of that:

C++

//invoke.cpp
//compile with: cl /EHsc /LD /nologo invoke.cpp
#include <stdio.h>

static void test_callback() 
{
    printf("test_callback called\n");
}

extern "C" __declspec( dllexport ) void* getPointer()
{
    return (void*)&test_callback; //Return a raw pointer to the test_callback function.
}

C#

//invoke.cs
//compile with: csc /nologo invoke.cs
using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport( "invoke.dll" )]
    private static extern IntPtr getPointer();

    private delegate void TestCallbackDelegate(); //Delegate that matches the signature of test_callback

    static void main()
    {
        IntPtr ptr = getPointer(); //Fetch the native void pointer.
        TestCallbackDelegate test_callback = Marshal.GetDelegateForFunctionPointer<TestCallbackDelegate>( ptr ); //Marshal the void pointer to a delegate.
        test_callback(); //Invoke the native C function.
    }
}

I used the `DllImport` attribute to avoid having to invoke the CLR as you're doing, but it's the same idea.

EDIT: Because I realized the above doesn't apply to what the OP was asking, I'll include an updated and proper sample. The above will remain for posterity.

C

#define COBJMACROS

#include <stdio.h>
#include <windows.h>
#include <mscoree.h>

static void test_callback()
{
    printf( "test_callback has been called.\n" );
}

int main( void )
{
    HRESULT status;
    ICLRRuntimeHost *Host;
    BOOL Started;
    DWORD Result;

    Host = NULL;
    Started = FALSE;

    status = CorBindToRuntimeEx( NULL, NULL, 0, CLSID_CLRRuntimeHost, IID_ICLRRuntimeHost, (void**)&Host );

    if( FAILED( status ) )
        goto cleanup;

    status = ICLRRuntimeHost_Start( Host );

    if( FAILED( status ) )
        goto cleanup;

    Started = TRUE;

    int ptr = (int)&test_callback;
    printf( "test_callback is at 0x%X\n", ptr );

    char param[5];
    param[0] = 0xFF & ( ptr >> 0 );
    param[1] = 0xFF & ( ptr >> 8 );
    param[2] = 0xFF & ( ptr >> 16 );
    param[3] = 0xFF & ( ptr >> 24 );
    param[4] = '\0';

    status = ICLRRuntimeHost_ExecuteInDefaultAppDomain( Host, L"invoke.dll", L"InteropTesting.Invoker", L"InvokeCallback", (LPCWSTR)param, &Result );

    if( FAILED( status ) )
        goto cleanup;

cleanup:
    if( Started )
        ICLRRuntimeHost_Stop( Host );

    if( Host != NULL )
        ICLRRuntimeHost_Release( Host );

    return SUCCEEDED( status ) ? 0 : 1;
}

C#

using System;
using System.Runtime.InteropServices;

namespace InteropTesting
{
    public static class Invoker
    {
        private delegate void TestCallbackDelegate();

        public static int InvokeCallback( string param )
        {
            //C# has a built-in means of turning byte arrays into integers
            //so we'll use BitConverter instead of using the bitwise operators.
            char[] chars = param.ToCharArray();
            int ptr = BitConverter.ToInt32( Array.ConvertAll( chars, c => (byte)c ), 0 );

            var test_callback = (TestCallbackDelegate)Marshal.GetDelegateForFunctionPointer( new IntPtr( ptr ), typeof( TestCallbackDelegate ) );
            test_callback();

            return 0;
        }
    }
}

Problem

I have a static function in my C program which address is transmitted to a C# .NET program. The address is correct, but is it possible to call this function within C#? Have some Code: ``` static void test_callback() { printf("test_callback called\n"); } void callCSharpFunction () { HRESULT status; BOOL Started; DWORD result; char ptr[5]; int p1; Started = FALSE; status = CorBindToRuntimeEx( NULL, NULL, 0, &CLSID_CLRRuntimeHost, &IID_ICLRRuntimeHost, (PVOID *)&Host ); if (FAILED(status)) {} status = ICLRRuntimeHost_Start(Host); if (FAILED(status)) {} Started = TRUE; p1 = (int)(&test_callback); ptr[0] = 0xFF & ((int)&test_callback >> 0); ptr[1] = 0xFF & ((int)&test_callback >> 8); ptr[2] = 0xFF & ((int)&test_callback >> 16); ptr[3] = 0xFF & ((int)&test_callback >> 24); printf("test_callback is at 0x%X\n", (int)&test_callback); status = ICLRRuntimeHost_ExecuteInDefaultAppDomain( Host, L"C:\\pathtodll\\mydll.dll", L"myclass", L"myfunction", (LPCWSTR)ptr, &result ); printf("Result is 0x%X\n", result); } ``` And in my C# .NET project I have ``` public static unsafe void callCallback(int ptr) { void (*callback)(); // I wish I could do that but "unsafe" seems not to allow function pointers .. callback = (void(*)())ptr; callback(); } public static int test(string param) { char[] ptrChar = param.ToCharArray(); int ptrInt = 0; ptrInt = ( ((int)(0xFF00 & (int)ptrChar[1]) | (0x00FF & (int)ptrChar[1])) << 16 ) | (int)(0xFF00 & (int)ptrChar[0]) | (0x00FF & (int)ptrChar[0]); callCallback(ptrInt); } ```

Original source