通过嵌入式Mono将C ++函数指针传递给C#

时间:2018-08-18 14:03:44

标签: c# c++ c mono

我有一个C#方法,如下所示:

public delegate void VariableObserver(string variableName, object newValue);

public void ObserveVariable(string variableName, VariableObserver observer)
{
    // stuff
}

此代码已嵌入到c ++应用程序中,我想从C ++调用ObserveVariable函数,并传递一个函数指针或与VariableObserver委托等效的东西。这样的目的是C#代码可以调用委托,并且C ++函数将被调用。

我习惯使用mono_runtime_invoke来调用C#函数,并且效果很好。但是,我找不到任何有关如何传递函数指针/委托的文档的有用示例。您是否需要像使用字符串等某些类型那样将其装箱?如果是这样,您该怎么做?甚至有可能吗?

我在四处搜索时发现了Marshal.GetDelegateFromFunctionPointer方法,我想可以在C#中使用它来获取委托并正常进行,但是these docs说这已经过时了。

编辑:我发现了更多东西。这里有一个更新的Marshal函数:Marshal.GetDelegateForFunctionPointer<TDelegate>(IntPtr)看起来很有希望,但它明确表示“您不能将此函数与通过C ++或从GetFunctionPointer方法获得的函数指针一起使用”。 :(

Edit2:我已经尝试过仅使用GetDelegateForFunctionPointer的建议,但是看起来函数指针没有正确编组。看看:

C#代码:

delegate void TestObserver(int num);

public void BindObserver(IntPtr observerFuncPtr)
{
    TestObserver obs = Marshal.GetDelegateForFunctionPointer<TestObserver>(observerFuncPtr);
    obs(1337);
}

C ++代码:

static void ObserverCallback(int num)
{
    printf("WE GOT A CALLBACK %d", num);
}

// inside a function I call

void* params[1];
params[0] = &ObserverCallback;

MonoObject* exception;
mono_runtime_invoke(theMonoMethod, theMonoInstance, params, &exception);

但是这样做会导致C#错误:

Runtime Exception : System.NullReferenceException: Object reference not set to an instance of an object
  at (wrapper managed-to-native) System.Object:wrapper_native_8348575608244C89 (int)
  at InkGlue.GlueStory.BindObserver (System.IntPtr observerFuncPtr) [0x00006] in <78fcd644f8db43978f6f7b1655d0ab2f>:0 

这使我相信函数指针未成功传递给C#。有关如何正确执行此操作的任何信息?

2 个答案:

答案 0 :(得分:1)

简单的解决方法是C填充。 https://stackoverflow.com/a/31232805/179795和该问题的其他答案也可能有帮助。

答案 1 :(得分:0)

我认为,如果您将Marshal.GetDelegateForFunctionPointer传递给标记为static的函数的地址,它将起作用。如有必要,将this作为显式参数传递。