【问题标题】:Pass a C++ function pointer to C# with embedded mono将 C++ 函数指针传递给带有嵌入式单声道的 C#
【发布时间】:2019-01-25 07:51:09
【问题描述】:

我有一个如下所示的 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# 中使用它来获取 delgate 并照常进行,但是 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#。有关如何正确执行此操作的任何信息?

【问题讨论】:

  • 尝试将extern “C” 添加到 ObserverCallback 的声明中,以确保它遵循 C 调用约定。
  • 您可能还需要在委托声明中使用[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
  • &ObserverCallback 不是正确的函数指针。您缺少函数指针类型 - 请参阅:stackoverflow.com/questions/2298242/callback-functions-in-c

标签: c# c++ c mono


【解决方案1】:

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

【讨论】:

  • 谢谢,但我只有这个小用例,我觉得采用它对于这么小的问题来说太大了。目前正在考虑完全以另一种方式进行。
【解决方案2】:

我认为Marshal.GetDelegateForFunctionPointer 将工作,如果你传递一个标记为static 的函数的地址。如有必要,将this 作为显式参数传递。

【讨论】:

    猜你喜欢
    • 2011-04-17
    • 2012-02-22
    • 1970-01-01
    • 2011-05-22
    • 1970-01-01
    • 2013-04-28
    • 1970-01-01
    • 2019-03-12
    相关资源
    最近更新 更多