如何将c++类转换为托管类并在其中调用纯虚函数?
本文关键字:在其中 调用 函数 c++ 转换 | 更新日期: 2023-09-27 18:19:00
看起来是这样的
#include <stdio.h>
#define __dllexport extern "C" __declspec(dllexport)
class PureVirtual
{
public:
virtual void Foo() = 0;
};
class ImplPureVirtual : public PureVirtual
{
public:
void Foo()
{
printf("Moo");
}
};
__dllexport PureVirtual* GetPV();
在实现:#include "ManagedClass.h"
PureVirtual* impl = new ImplPureVirtual;
__dllexport PureVirtual* GetPV()
{
return impl;
}
编译为TestFoo.dll,然后在c#中
class Program
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string strFileName);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string strProcName);
static void Main(string[] args)
{
var ptrLib = LoadLibrary("TestFoo.dll");
if (ptrLib != IntPtr.Zero)
{
var ptrAddr = GetProcAddress(ptrLib, "GetPV");
if (ptrAddr != IntPtr.Zero)
// Now we have the pointer object, what should I do next?
}
Console.ReadLine();
}
}
我认为这是一个相当好的问题,如果一个软件公司向公众发布他们的非托管API(只有纯虚拟方法),如果我们可以控制c++抽象和多态性的智慧,那么我们可以把它变成托管的,并有几个好处!例如垃圾控制,泛型,以及广泛的引用和库选择。
还需要为每个虚成员定义一个extern "C"
函数;由于c++名称混淆,托管代码不能以一种简单或可移植的方式调用非托管c++导出。例如:
__dllexport void PureVirtual_Foo(PureVirtual * pv)
{
pv->Foo();
}
另外,考虑到您需要在extern "C"
包装器中捕获c++异常,因为未捕获的异常可能跳过托管堆栈帧,导致CLR进入坏状态。
我强烈建议您考虑使用SWIG。它能够自动为您生成这些包装器。
注意,你不需要使用LoadLibrary()
等,你可以只p/调用函数:
[DllImport("TestFoo")]
public static extern IntPtr GetPV();
同样地,调用我的示例包装器中的虚方法:
[DllImport("TestFoo")]
public static extern void PureVirtual_Foo(IntPtr pv);
那么你可以像这样调用虚方法:
PureVirtual_Foo(GetPV());