c++互操作:如何从本机c++调用c#类?

时间:2022-06-14 05:19:17

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包装器:

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.

我想到了两个选择。

  1. Expose the class as a COM object and use it as a COM object from C++.
  2. 将类公开为COM对象,并将其用作来自c++的COM对象。
  3. Create a static C# class that exposes an interface to interact with the non-static C# class.
  4. 创建一个静态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.

我想到了两个选择。

  1. Expose the class as a COM object and use it as a COM object from C++.
  2. 将类公开为COM对象,并将其用作来自c++的COM对象。
  3. Create a static C# class that exposes an interface to interact with the non-static C# class.
  4. 创建一个静态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键也可以编译源代码。