简体   繁体   中英

C++ Interop: How do I call a C# class from native C++, with the twist the class is non-static?

I have a large application written in native C++. I also have a class in C# that I need to call.

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.

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).

Has anyone run into this problem before - how do I export a non-static C# class to native C++?


Update 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:

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++/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.

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;
}

Two options come to mind.

  1. Expose the class as a COM object and use it as a COM object from C++.
  2. Create a static C# class that exposes an interface to interact with the non-static C# class.

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.

The main idea behind this technique described by Paul DiLascia in his two remarkable articles:

Managed Code in Visual Studio 2005

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

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM