如何将委托或函数指针从 C# 传递到 C++ 并使用 InternalCall 调用它

How to pass a delegate or function pointer from C# to C++ and call it there using InternalCall(如何将委托或函数指针从 C# 传递到 C++ 并使用 InternalCall 调用它)

本文介绍了如何将委托或函数指针从 C# 传递到 C++ 并使用 InternalCall 调用它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 C# 中有以下设置:

I have the following setup in 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...
");
    setCallback(callback01);
}

public void callback01(string message)
{
    System.Console.Write("callback 01 called: " + message + "
");
}

这在 C++ 中(该函数通过 mono_add_internal_call 正确注册):

And this in C++ (the function is registered correctly via 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++ 函数并将 something 传递给委托变量.但是现在呢?

The C++-function is called and something is passed to the delegate variable. But what now?

我环顾四周,发现函数mono_delegate_to_ftnptr"被提到了几次,从这些例子来看,它似乎正是我所需要的.
然而,这个函数在我的mono(4.6)发行版中似乎根本不存在,所以我只能猜测它不再存在了.

I looked around and found the function "mono_delegate_to_ftnptr" mentioned a few times, and from those examples it seems to be exactly what I need.
However, this function simply does not seem to exist in my distribution of mono (4.6), so I can only guess it does not exist any more.

我还找到了一些如何使用 PInvoke 执行此操作的示例.这是我不想使用的东西 - 因为 InternalCall 对于我的目的来说要快得多.
当然,如果 PInvoke 是唯一的方法,那就这样吧,但我对此表示怀疑.

I also found a few examples of how to do this with PInvoke. Which is something I do not want to use - since InternalCall is much faster for my purpose.
Of course, if PInvoke would be the only way, so be it, but I doubt that.

到最后,我真的不知道如何从这里开始.

In the end, I am really at a loss at how to proceed from here.

推荐答案

经过几个小时的挖掘,我终于找到了一个(?)解决方案.
基本上,适用于 PInvoke 方法的方法在这里也适用,您可以将函数指针而不是委托从 C# 传递到 C(++).
我更喜欢一个可以直接传递委托的解决方案,但你总是可以在 C# 中添加一些包装器代码,至少让它看起来像这样.

After some more hours of digging I finally found a (the?) solution.
Basically, what works for the PInvoke approach works here as well, you can pass a function pointer instead of a delegate from C# to C(++).
I'd prefer a solution where you can pass a delegate directly, but you can always add some wrapper code in C# to at least make it look like that.

解决方案:

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...
");
    del = new CallbackDelegate(callback01);
    setCallback(Marshal.GetFunctionPointerForDelegate(del));

    System.Console.Write("Calling passed C++ callback...
");
}

public void callback01(string message)
{
    System.Console.Write("callback 01 called. Message: " + message + "
");
}

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# 中(这就是我将其分配给del"的原因),否则它将被 GC 捕获并且您的回调将变得无效.
当然,这是有道理的,但我觉得在这种情况下很容易忘记.

Watch out, though: You need to keep the delegate around in C# somehow (which is why I assigned it to "del") or it will be caught by the GC and your callback will become invalid.
It makes sense, of course, but I feel this is easy to forget in this case.

这篇关于如何将委托或函数指针从 C# 传递到 C++ 并使用 InternalCall 调用它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:如何将委托或函数指针从 C# 传递到 C++ 并使用 InternalCall 调用它

基础教程推荐