Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call C++ functions from C#/.NET

I have a solution which has a C++ project and a C# project.

The C++ project defines a class, which I want to instantiate in C# and call its member functions. So far I managed to instantiate the class:

CFoo Bar = new CFoo();

But when I try to call a function on it, the compiler says, it is not available.

Also, when I inspect the object in the debugger, no members are shown.

What am I missing here?

like image 997
clamp Avatar asked Jan 23 '23 09:01

clamp


1 Answers

You need to declare the class in C++/CLI as a ref class.

(Note that we're talking about C++/CLI, not C++. I assume you must have enabled the CLR in your C++ project or you wouldn't be able to get the new CFoo to work.)

Edit:

You don't need to convert all your old classes in to ref classes.

Suppose you have some old C++:

class FooUnmanaged
{
    int x;

    FooUnmanaged() : x(5) {}
};

Then you try to wrap it in a CLR class:

ref class FooManaged
{
    FooUnmanaged m;
};

As you've noticed, you get an error saying this isn't allowed. But try this:

ref class FooManaged
{
    FooUnmanaged *m;
};

That's perfectly OK. The compiler doesn't want to allocate an instance of an unmanaged object embedded inside an object on the managed heap, but it's quite happy to have a pointer, which it turns into System.IntPtr in the resulting IL.

This means that you have to make a decision about how to call delete. The most likely solution is:

ref class FooManaged
{
    FooUnmanaged *u;

public:
    FooManaged(FooUnmanaged *u_)
        : u(u_) { }

    ~FooManaged() { delete u; }
};

Just as it would be in any other C++ class. It's possible that C++/CLI will be able to do this translation for us automatically in some future version.

Note that the resulting IL is that the FooManaged class now implements IDisposable, and the destructor has been turned into a Dispose method. This allows .NET clients to properly deallocate it, e.g. in C#

using (var m = new FooManaged())
{

    // end of block: m will be disposed (and so FooUnmanaged will be deleted)
}
like image 97
Daniel Earwicker Avatar answered Jan 29 '23 14:01

Daniel Earwicker