我在C#中进行了以下设置:
public delegate void CallbackDelegate(string message);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public static extern void setCallback(CallbackDelegate aCallback);
public void testCallbacks()
{
System.Console.Write("Registering C# callback...\n");
setCallback(callback01);
}
public void callback01(string message)
{
System.Console.Write("callback 01 called: " + message + "\n");
}
这在C ++中(函数通过mono_add_internal_call正确注册):
typedef void (*CallbackFunction)(const char*);
void setCallback(MonoDelegate* delegate)
{
// How to convert the MonoDelegate to a proper function pointer?
// So that I can call it like func("test");
}
调用C ++函数并将某些传递给委托变量。 但现在呢?
我环顾四周,找到了函数" mono_delegate_to_ftnptr"提到了几次,从这些例子来看,它似乎正是我所需要的 但是,这个函数似乎在我的mono(4.6)分布中似乎不存在,所以我只能猜测它不再存在了。
我还发现了一些如何使用PInvoke执行此操作的示例。这是我不想使用的东西 - 因为InternalCall对我的目的要快得多 当然,如果PInvoke是唯一的方式,那就这样吧,但我对此表示怀疑。
最后,我真的不知道如何从这里开始。
答案 0 :(得分:10)
经过几个小时的挖掘后,我终于找到了一个(?)解决方案
基本上,对PInvoke方法有效的方法也适用于此,您可以将函数指针而不是C#中的委托传递给C(++)。
我更喜欢一个可以直接传递委托的解决方案,但是你总是可以在C#中添加一些包装代码,至少让它看起来像那样。
<强>解决方案:强>
C#:
public delegate void CallbackDelegate(string message);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
public static extern void setCallback(IntPtr aCallback);
private CallbackDelegate del;
public void testCallbacks()
{
System.Console.Write("Registering C# callback...\n");
del = new CallbackDelegate(callback01);
setCallback(Marshal.GetFunctionPointerForDelegate(del));
System.Console.Write("Calling passed C++ callback...\n");
}
public void callback01(string message)
{
System.Console.Write("callback 01 called. Message: " + message + "\n");
}
C ++:
typedef void (*CallbackFunction)(MonoString*);
void setCallback(CallbackFunction delegate)
{
std::cout << &delegate << std::endl;
delegate(mono_string_new(mono_domain_get(), "Test string set in C++"));
}
请注意:您需要以某种方式将代理保留在C#中(这就是为什么我将其分配给&#34; del&#34;)或者它将被GC捕获并且您的回调将变为无效。
当然,这是有道理的,但我觉得在这种情况下很容易忘记。
答案 1 :(得分:0)
您可以使用intptr_t将函数指针作为c ++中的参数传递给c#。
MSDN不准确,下面的代码行得通。
// c++
static void func(int param)
{
//...
}
void other_func()
{
ptr->SetCallback( reinterpret_cast<intptr_t>(func));
}
// c#
public static mydelegatetype somefunc = null;
public void SetCallback(IntPtr function_pointer)
{
somefunc = (mydelegatetype)
Marshal.GetDelegateForFunctionPointer(function_pointer, typeof(mydelegatetype));
}