我有一个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#。有关如何正确执行此操作的任何信息?
答案 0 :(得分:1)
简单的解决方法是C填充。 https://stackoverflow.com/a/31232805/179795和该问题的其他答案也可能有帮助。
答案 1 :(得分:0)
我认为,如果您将Marshal.GetDelegateForFunctionPointer
传递给标记为static
的函数的地址,它将起作用。如有必要,将this
作为显式参数传递。