我可以通过
从C#调用C ++包装器类[DllImport("SomeDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void M();
我在C ++代码中的位置
extern "C" { __declspec(dllexport) BSTR GroupTerm(); }
void M() { /* Do Stuff */ }
这很有效,但由于多种原因,我想在方法中包含方法M
class SomeClass {
public:
void M();
}
我尝试过做
class SomeClass {
public:
void __declspec(dllexport) M();
}
其中
void __declspec(dllexport) SomeClass::M() { /* Do Stuff */ }
但是C#代码(使用上面声明的导入的C#代码)找不到入口点并抛出异常。 我的问题是,如何导出此方法M()
[这是SomeClass
的公共成员,以便与C#的interop / pinvoke一起使用?
感谢您的时间。
答案 0 :(得分:2)
有几种方法,都有不同的好处。
更简单的一个是为你的C ++类制作一个C-wrapper(我太懒了,不能放入装饰,你应该自己做)。
class SomeClass {
public:
void M();
};
void* MakeSomeClass() {return new SomeClass();}
void DestroySomeClassHandle(void* handle) { delete (SomeClass*)handle;}
void M(void* handle) { ((SomeClass*)handle)->M();}
然后像往常一样导入C函数。
这样做的好处是你不必做任何你目前不熟悉的事情。更多的东西(Matlab,Python,ect)有类似于PInvoke的东西,所以这使你的代码更具跨语言可用性。
缺点是这是超级错误,你扔掉了很多类型的安全。
更好的方法(imho)是为类
制作C ++ / CLI包装器public ref class ManageSomeClass
{
public:
ManageSomeClass() {myclass_ = new SomeClass();}
!ManageSomeClass() { if (myclass) {delete myclass; myclass_ = NULL;} }
~ManageSomeClass() { this->!ManageSomeClass(); }
void M() { myclass_->M();}
private:
SomeClass* myclass_;
};
我使用SomeClass作为显示析构函数终结符的指针,但它不需要是指针。它可能是一个完整的实例。最重要的是,它将被编译成.NET类(在dll中),您可以将其导入到C#代码中。然后呼叫是:
//c# code
ManageSomeClass msc = new ManageSomeClass();
msc.M();
上行是从托管到非托管的灵活性。缺点是你突然维持另一个界面。如果你有继承/多态,你的包装器必须镜像该结构。这也是维持的噩梦。
编辑:另一个缺点是你必须学习C ++ / CLI,它是(kindof)和C ++的扩展,也是(kindof)一种完全不同的语言。
最后一种方法是通过COM接口。 http://msdn.microsoft.com/en-us/library/aa645736%28v=vs.71%29.aspx。您可以在C#中使用在C ++中使用的相同COM导入调用(有一些细微差别)来实例化和调用COM类。但是你需要学习COM(我从未做过),然后以COM投诉方式实现你的课程。但是你有一个COM接口,可以在整个Windows上导入。
答案 1 :(得分:1)
假设该方法是静态的,您有几个选择:
EntryPoint
DllImport
参数找到它。 坦率地说,选项3是我要选择的。
当您使用成员函数时,您需要导出接受实例指针作为其第一个参数的函数。而且您可能必须导出实例化对象的函数。
那说,并回应您的意见,其他可能更好的解决方案是:
答案 2 :(得分:1)
另一种方法(除了@MadScienceDreams和@DavidHeffernan所说的)是将您的C ++代码转换为Windows运行时DLL,然后它可以在您的C#代码中使用。请参阅此处了解详细信息和示例:Creating Windows Runtime Components in C++
摘自链接:
文章介绍了如何使用C ++创建Windows运行时组件, 这是一个可以从构建的Windows应用商店应用程序调用的DLL 使用JavaScript或C#,Visual Basic或C ++
...
通常,在编写C ++组件代码时,请使用常规C ++ 库和内置类型,但在抽象二进制接口除外 (ABI)边界,您将数据传入另一个的代码 .winmd包。在那里,使用Windows运行时类型和特殊 Visual C ++支持创建和操作它们的语法 类型。此外,在Visual C ++代码中,使用类型,如 委托和事件来实现可以从您的事件中触发的事件 组件并在JavaScript,Visual Basic或C#中处理。
以下是“使用C ++创建Windows运行时组件”的sample code。