C ++ Interop:如何从本机C ++调用C#类,并且该类是非静态的?

我有一个用本机C ++编写的大型应用程序。 我还有一个C#课我需要打电话。

如果C#类是静态的,那么它将是微不足道的(Web上有很多例子) – 只需编写混合的C ++ / CLI包装器,导出接口,然后就完成了。

但是,C#类是非静态的,并且不能更改为静态,因为它有一个接口(如果您尝试使C#类静态,编译器将生成错误)。

有没有人遇到过这个问题 – 如何将非静态C#类导出到本机C ++?


更新2010-11-09

最终的解决方案:尝试COM,这很好用,但不支持结构。 所以,使用C ++ / CLI包装器,因为我绝对需要能够在C ++和C#之间传递结构。 我根据这里的代码编写了一个混合模式.dll包装器:

  • 如何:使用C ++ Interop的Marshalarrays

  • 如何:使用C ++ Interop的Marshal结构

由于目标类是非静态的,我不得不使用单例模式来确保我只实例化目标类的一个副本。 这确保一切都足够快,以满足规格。

如果你想让我发布一个演示项目,请联系我(虽然,公平地说,我从C ++调用C#,而现在大多数人都希望从C#调用C ++)。

与静态类一样,C ++ / CLI或COM互操作也适用于非静态类。 使用C ++ / CLI,您只需引用包含非静态类的程序集,然后您可以使用gcnew来获取对新实例的引用。

是什么让你觉得这对你的非静态课是不可能的?

编辑:这里有示例代码。

 using namespace System; public ref class CSquare { private: double sd; public: CSquare() : sd(0.00) {} CSquare(double side) : sd(side) { } ~CSquare() { } property double Side { double get() { return sd; } void set(double s) { if( s <= 0 ) sd = 0.00; else sd = s; } } property double Perimeter { double get() { return sd * 4; } } property double Area { double get() { return sd * sd; } } }; array ^ CreateSquares() { array ^ sqrs = gcnew array(5); sqrs[0] = gcnew CSquare; sqrs[0]->Side = 5.62; sqrs[1] = gcnew CSquare; sqrs[1]->Side = 770.448; sqrs[2] = gcnew CSquare; sqrs[2]->Side = 2442.08; sqrs[3] = gcnew CSquare; sqrs[3]->Side = 82.304; sqrs[4] = gcnew CSquare; sqrs[4]->Side = 640.1115; return sqrs; } 

我想到了两种选择。

  1. 将该类公开为COM对象,并将其用作C ++中的COM对象。
  2. 创建一个静态C#类,公开一个接口以与非静态C#类进行交互。

几年前我已经调查了这个话题:我想使用原生代码中的log4net和Npgsql库,即使没有/ clr键也可以编译。

Paul DiLascia在他的两篇非凡文章中描述了这种技术背后的主要思想:

Visual Studio 2005中的托管代码

使用我们的ManWrap库在Native C ++代码中获得最佳.NET

这个解决方案的主要思想是gcroot智能指针和intptr_t在内存中具有完全相同的表示。 我们创建了一个名为GCROOT(T)的宏,它在托管代码中使用gcroot,在非托管代码中使用intptr_t。 我们使用本机接口和托管实现创建DLL,并使用本机代码中的dll。

我很容易为托管类创建一些适配器并在本机C ++世界中使用它们,即使没有/ clr密钥也可以编译我的源代码。