c# - 从 C# 导入 C++ 类方法

标签 c# c++ import interop pinvoke

我可以通过 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#代码(使用上面声明的import的C#代码)找不到入口点,抛出异常。 我的问题是,如何导出此方法 M() [这是SomeClass的公共(public)成员|与 C# 的互操作/pinvoke 一起使用?

感谢您的宝贵时间。

最佳答案

好吧,有几种方法,都有不同的优点。

其中一个更简单的方法是为您的 C++ 类制作一个 C 包装器(我懒得装饰,您应该自己动手)。

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 等)都具有与 PInvoke 类似的东西,因此这使您的代码更易于跨语言使用。

缺点是这非常容易出错,而且您会丢掉很多类型安全性。

更好的方法(恕我直言)是为该类创建一个 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();

好处是可以像这样从托管到非托管的灵 active 。缺点是您突然要维护另一个接口(interface)。如果你有继承/多态性,你的包装器必须反射(reflect)那个结构。这也是维护的噩梦。

编辑:另一个缺点是您必须学习 C++/CLI,这是 C++ 的 (kindof) 和扩展,也是 (kindof) 完全不同的语言。

最后一种方法是通过 COM 接口(interface)。 http://msdn.microsoft.com/en-us/library/aa645736%28v=vs.71%29.aspx .您可以在 C# 中使用在 C++ 中使用的相同 COM 导入调用(有一些细微差别)来实例化和调用 COM 类。但是你需要学习 COM(我从来没有学过),然后以 COM 投诉的方式实现你的类。但是你有一个 COM 接口(interface),它可以在整个 Windows 中导入。

关于c# - 从 C# 导入 C++ 类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22817687/

相关文章:

C# KeyPress 事件不会将最后一个字符从文本框复制到表单的文本属性

C# XNA 4.0 检查是否按下了除一个之外的任何键

c++ - 如何处理具有相同 namespace 的多个导入?

c++ - 从 `boost::static-visitor` 派生以删除代码重复

java - 无法从 jar 导入类

c# - 在 C# 中显示打印预览

c# - 使用 C# 和 AutoIt 向 Flash 游戏发送消息

c++ - iOS 上的 QGestures

sql-server - 将数据从 Access 导入到 SQL Server(对表进行少量更改)

python-3.x - 模块未找到错误: No module named '__main__.xxxx' ; '__main__' is not a package