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

时间:2010-10-07 15:10:34

标签: c# c++ interop c++-cli

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

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

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

之前是否有人遇到此问题 - 如何将非静态C#类导出到本机C ++?


更新2010-11-09

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

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

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

3 个答案:

答案 0 :(得分:10)

C ++ / CLI或COM interop与非静态类一样,与静态类一样。使用C ++ / CLI,您只需引用包含非静态类的程序集,然后使用gcnew获取对新实例的引用。

是什么让你认为这对你的非静态课程是不可能的?

编辑:有示例代码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;
}

答案 1 :(得分:3)

有两种选择。

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

答案 2 :(得分:1)

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

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

Managed Code in Visual Studio 2005

Use Our ManWrap Library to Get the Best of .NET in Native C++ Code

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

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