I have a large application written in native C++. I also have a class in C# that I need to call.
我有一个用本机c++编写的大型应用程序。我也有一个c#的类,我需要调用。
If the C# class was static, then it would be trivial (there's lots of examples on the web) - just write the mixed C++/CLI wrapper, export the interfaces, and you're done.
如果c#类是静态的,那么它就很简单(web上有很多示例)——只需编写混合的c++ /CLI包装器,导出接口,就可以了。
However, the C# class is non-static, and can't be changed to static as it has an interface (the compiler will generate an error if you attempt to make the C# class static).
但是,c#类是非静态的,并且不能因为它有一个接口而更改为静态的(如果您试图使c#类成为静态的,编译器将生成错误)。
Has anyone run into this problem before - how do I export a non-static C# class to native C++?
以前有人遇到过这个问题——我如何将一个非静态的c#类导出到本机c++ ?
Update 2010-11-09
更新2010-11-09
Final solution: tried COM, this worked nicely but didn't support structures. So, went with a C++/CLI wrapper, because I absolutely needed to be able to pass structures between C++ and C#. I wrote a mixed mode .dll wrapper based on the code here:
最终解决方案:尝试COM,它工作得很好,但是不支持结构。因此,我选择了c++ /CLI包装器,因为我绝对需要能够在c++和c#之间传递结构。我基于这里的代码编写了一个混合模式。dll包装器:
-
How to: Marshal Arrays Using C++ Interop
如何:使用c++互操作编组数组
-
How to: Marshal Structures Using C++ Interop
如何:使用c++互操作编组结构
As the target class was non-static, I had to use the singleton pattern to make sure I was only instantiating one copy of the target class. This ensured everything was fast enough to meet the specs.
由于目标类是非静态的,所以我必须使用单例模式来确保只实例化目标类的一个副本。这确保了一切都足够快以满足规格要求。
Contact me if you want me to post a demo project (although, to be fair, I'm calling C# from C++, and these days most people want to call C++ from C#).
如果你想让我发布一个演示项目,请联系我(不过,公平地说,我是从c++调用c#,现在大多数人都想从c#调用c++)。
3 个解决方案
#1
10
C++/CLI or COM interop work just as well with non-static classes as with static. Using C++/CLI you just reference your assembly that holds the non-static class and then you can use gcnew
to obtain a reference to a new instance.
c++ /CLI或COM interop与非静态类和静态类一样工作。使用c++ /CLI您只需引用包含非静态类的程序集,然后可以使用gcnew获取对新实例的引用。
What makes you think that this is not possible with your non-static class?
是什么让你认为这在非静态类中是不可能的?
EDIT: there is example code here.
编辑:这里有示例代码。
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<CSquare ^> ^ CreateSquares()
{
array<CSquare ^> ^ sqrs = gcnew array<CSquare ^>(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;
}
#2
3
Two options come to mind.
我想到了两个选择。
- Expose the class as a COM object and use it as a COM object from C++.
- 将类公开为COM对象,并将其用作来自c++的COM对象。
- Create a static C# class that exposes an interface to interact with the non-static C# class.
- 创建一个静态c#类,该类公开一个接口以与非静态c#类交互。
#3
1
I've investigated this topic couple of years ago: I want to use log4net and Npgsql libraries from native code that compiles even without /clr key.
几年前,我研究过这个主题:我想使用log4net和Npgsql库,它们来自于无需/clr键就能编译的本地代码。
The main idea behind this technique described by Paul DiLascia in his two remarkable articles:
Paul DiLascia在他的两篇杰出文章中描述了这种技术背后的主要思想:
Managed Code in Visual Studio 2005
Visual Studio 2005中的托管代码。
Use Our ManWrap Library to Get the Best of .NET in Native C++ Code
使用我们的ManWrap库,在本机c++代码中充分利用。net
The main idea in this solution that gcroot smart pointer and intptr_t have exactly the same representation in memory. And we creating a macro called GCROOT(T) that uses gcroot in Managed code and intptr_t in unmanaged. And that we create DLL with native interface and managed implementation and uses this dll from our native code.
该解决方案的主要思想是gcroot智能指针和intptr_t在内存中具有完全相同的表示。我们创建了一个名为GCROOT(T)的宏,它在托管代码中使用GCROOT,在unmanaged中使用intptr_t。我们使用本机接口和托管实现创建DLL,并使用本机代码中的DLL。
It was pretty easy for me create some adapter for my managed classes and use them in native C++ world and compile my source code even without /clr key.
我很容易为我的托管类创建一些适配器,并在本机c++世界中使用它们,即使没有/clr键也可以编译源代码。
#1
10
C++/CLI or COM interop work just as well with non-static classes as with static. Using C++/CLI you just reference your assembly that holds the non-static class and then you can use gcnew
to obtain a reference to a new instance.
c++ /CLI或COM interop与非静态类和静态类一样工作。使用c++ /CLI您只需引用包含非静态类的程序集,然后可以使用gcnew获取对新实例的引用。
What makes you think that this is not possible with your non-static class?
是什么让你认为这在非静态类中是不可能的?
EDIT: there is example code here.
编辑:这里有示例代码。
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<CSquare ^> ^ CreateSquares()
{
array<CSquare ^> ^ sqrs = gcnew array<CSquare ^>(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;
}
#2
3
Two options come to mind.
我想到了两个选择。
- Expose the class as a COM object and use it as a COM object from C++.
- 将类公开为COM对象,并将其用作来自c++的COM对象。
- Create a static C# class that exposes an interface to interact with the non-static C# class.
- 创建一个静态c#类,该类公开一个接口以与非静态c#类交互。
#3
1
I've investigated this topic couple of years ago: I want to use log4net and Npgsql libraries from native code that compiles even without /clr key.
几年前,我研究过这个主题:我想使用log4net和Npgsql库,它们来自于无需/clr键就能编译的本地代码。
The main idea behind this technique described by Paul DiLascia in his two remarkable articles:
Paul DiLascia在他的两篇杰出文章中描述了这种技术背后的主要思想:
Managed Code in Visual Studio 2005
Visual Studio 2005中的托管代码。
Use Our ManWrap Library to Get the Best of .NET in Native C++ Code
使用我们的ManWrap库,在本机c++代码中充分利用。net
The main idea in this solution that gcroot smart pointer and intptr_t have exactly the same representation in memory. And we creating a macro called GCROOT(T) that uses gcroot in Managed code and intptr_t in unmanaged. And that we create DLL with native interface and managed implementation and uses this dll from our native code.
该解决方案的主要思想是gcroot智能指针和intptr_t在内存中具有完全相同的表示。我们创建了一个名为GCROOT(T)的宏,它在托管代码中使用GCROOT,在unmanaged中使用intptr_t。我们使用本机接口和托管实现创建DLL,并使用本机代码中的DLL。
It was pretty easy for me create some adapter for my managed classes and use them in native C++ world and compile my source code even without /clr key.
我很容易为我的托管类创建一些适配器,并在本机c++世界中使用它们,即使没有/clr键也可以编译源代码。