从托管代码调用非托管方法

Calling unmanaged methods from managed code

本文关键字:方法 托管代码 调用      更新时间:2023-10-16

假设我有一个非托管类Test:

class Test
{
public:
    int SomeMethod(int a, bool b);
};

要创建一个新的Test实例,我会:

Test *test = new Test();

我的目标是嵌入Mono,以便托管代码可以在特定对象中调用非托管方法(如Test::SomeMethod)。我通过将该对象的指针传递给托管方法来表示该对象,如下所示:

void *args[1];
args[0] = &test;
mono_runtime_invoke(init, NULL, args, NULL);

以下是被调用的托管方法的样子:

public static void Init(IntPtr test)
{
}

从这里,我如何拨打Test.SomeMethod

我考虑过使用CALLI指令,使用System.Reflection.Emit,但我如何引用指针testInit的第一个参数)所指的对象?

我不想使用DllImport

您可能对CXXI感兴趣。它基于C++头创建一个托管程序集,并允许您像处理普通托管对象一样处理C++对象。

据我所知,它还没有完成,只能使用GCC编译的C++代码。

不能完成(或者至少不应该完成)。

您正试图直接混合两种完全不同的执行环境——DLLImport存在的原因是为了让编译器能够解决这个问题。

在.NET中,您可以创建混合模式应用程序(C++/CLI),允许托管代码和非托管代码在同一二进制文件中共存(并相互调用),但由于您谈论的是mono,因此我认为该选项已过时。

像.NET这样的托管环境具有严格的类型规则、垃圾收集和其他功能,这些功能根本不适用于非托管代码和数据。

如果不想使用DllImport,可以使用内部调用。看见https://github.com/mono/mono/blob/master/samples/embed/teste.cmono_ad_internal_call()调用和test.cs文件中的C#代码。这主要类似于DllImport,只是没有为您进行封送(例如,C#代码中的字符串对象将在C代码中显示为MonoString*,而不是char*)。

在任何情况下,请注意,可以使用DllImport访问的函数和使用mono_ad_internal_call()注册的函数指针都必须是C函数,而不是C++成员方法。