通过函数指针在C#中调用C函数

斯蒂芬·福克

我的C程序中有一个静态函数,该地址被传输到C#.NET程序。地址正确,但是可以在C#中调用此函数吗?

有一些代码:

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

在我的C#.NET项目中

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);
}
用户名

您将需要使用元帅。GetDelegateForFunctionPointer您甚至不需要使用不安全的代码。

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

尽管更简单的方法是将a传递void*给C#方法,它会自动编组到IntPtr这是一个最小的例子:

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.
    }
}

我使用该DllImport属性来避免在执行操作时必须调用CLR,但这是相同的想法。


编辑:因为我意识到以上内容不适用于OP所要求的内容,所以我将提供一个经过更新的适当示例。以上内容仅供后人参考。

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

通过函数指针在C#中调用C函数

来自分类Dev

从C#调用C dll中的函数,该函数将某种类型的指针返回到函数指针

来自分类Dev

函数指针分配并在C ++中调用?

来自分类Dev

通过HTML按钮调用C#函数

来自分类Dev

指向C#中的函数的指针

来自分类Dev

在C#中传递函数指针

来自分类Dev

从Javascript调用C ++函数指针

来自分类Dev

调用成员指针函数C ++

来自分类Dev

调用成员指针函数C ++

来自分类Dev

C:函数调用后的指针

来自分类Dev

C ++中的函数指针

来自分类Dev

通过基本指针的C ++显式析构函数调用

来自分类Dev

使用boost :: function通过函数指针调用C ++类方法

来自分类Dev

通过函数c传递指针

来自分类Dev

通过指针调用函数

来自分类Dev

通过指针调用函数

来自分类Dev

调用函数C#

来自分类Dev

C ++标准是否明确禁止通过constexpr成员函数指针进行的调用中的默认参数?

来自分类Dev

在C#中调用此C函数的正确语法是什么?该函数使用指针和数组

来自分类Dev

在C#文件中调用javascript函数

来自分类Dev

避免在C#中调用多个函数

来自分类Dev

在函数C#中调用事件

来自分类Dev

在C中的函数调用中为指针分配内存

来自分类Dev

在C中的函数调用中为指针分配内存

来自分类Dev

将C ++函数包装在返回指针的c#中

来自分类Dev

从C ++ / CLI函数调用C#函数

来自分类Dev

函数调用中的指针类型不兼容-C

来自分类Dev

指针声明和函数调用中的奇数C语法

来自分类Dev

如何调用以指针数组为参数的函数?在C中