从C#/ .NET调用C++函数

cla*_*amp 3 .net c# unmanaged c++-cli

我有一个有C++项目和C#项目的解决方案.

C++项目定义了一个类,我想在C#中实例化并调用其成员函数.到目前为止,我设法实例化了这个类:

CFoo Bar = new CFoo();
Run Code Online (Sandbox Code Playgroud)

但是当我尝试在其上调用函数时,编译器说,它不可用.

此外,当我在调试器中检查对象时,不会显示任何成员.

我在这里错过了什么?

Dan*_*ker 8

您需要在C++/CLI中将该类声明为ref class.

(请注意,我们讨论的是C++/CLI,而不是C++.我假设您必须在C++项目中启用CLR,否则您将无法使用新的CLR CFoo.)

编辑:

您不需要将所有旧类转换为ref类.

假设你有一些旧的C++:

class FooUnmanaged
{
    int x;

    FooUnmanaged() : x(5) {}
};
Run Code Online (Sandbox Code Playgroud)

然后尝试将其包装在CLR类中:

ref class FooManaged
{
    FooUnmanaged m;
};
Run Code Online (Sandbox Code Playgroud)

正如您所注意到的,您会收到错误消息,说明这是不允许的.但试试这个:

ref class FooManaged
{
    FooUnmanaged *m;
};
Run Code Online (Sandbox Code Playgroud)

那完全没问题.编译器不希望分配嵌入在托管堆上的对象内部的非托管对象的实例,但是很高兴有一个指针,它会System.IntPtr在生成的IL中变成.

这意味着您必须决定如何打电话delete.最可能的解决方案是:

ref class FooManaged
{
    FooUnmanaged *u;

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

    ~FooManaged() { delete u; }
};
Run Code Online (Sandbox Code Playgroud)

就像在任何其他C++类中一样.在将来的某个版本中,C++/CLI可能会自动为我们执行此转换.

请注意,生成的IL是FooManaged类现在实现的IDisposable,并且析构函数已经转换为Dispose方法.这允许.NET客户端正确地释放它,例如在C#中

using (var m = new FooManaged())
{

    // end of block: m will be disposed (and so FooUnmanaged will be deleted)
}
Run Code Online (Sandbox Code Playgroud)