将托管类成员传递给c ++方法

bob*_*lex 0 pointers c++-cli

我有一个C++ DLL与以下方法:

//C++ dll method (external)
GetServerInterface(ServerInterface* ppIF /*[OUT]*/)
{
//The method will set ppIF
}

//ServerInterface is defined as:
typedef void *  ServerInterface;
Run Code Online (Sandbox Code Playgroud)

为了从C#项目访问dll,我创建了一个C++/CLI项目并声明了一个托管类,如下所示:

public ref class ComWrapperManager
{
//
//
ServerInterface _serverInterface;
void Connect();
//
//
}
Run Code Online (Sandbox Code Playgroud)

我使用Connect()方法调用GetServerInterface,如下所示.第一次通话有效,第二次通话无效.有人可以解释原因吗?我需要将该指针持久化为托管类中的成员变量.有更好的方法吗?

    void Connect()
    {
    ServerInterface localServerInterface;
    GetServerInterface(&localServerInterface); //THIS WORKS

    GetServerInterface(&_serverInterface); //THIS DOESNT

    //Error 1   error C2664: 'ServerInterface ' : 
    //cannot convert parameter 1 from //'cli::interior_ptr<Type>' 
    //to 'ServerInterface *'


    }
Run Code Online (Sandbox Code Playgroud)

Han*_*ant 6

您正在将指针传递给托管对象的成员.这样的指针是特殊的,称为内部指针.它们由垃圾收集器跟踪,它将在GC压缩堆时移动托管对象时修改指针值.

问题是,您将该指针传递给非托管代码.GC无法修改本机代码正在使用的指针值的副本.现在,当另一个线程触发垃圾收集时,灾难就会发生,就像本机代码正在执行并取消引用指针一样.该对象不再存在于原始地址.非常非常糟糕.并且极难诊断,因为它不太可能发生.

编译器可以看到你犯了这个错误.并抱怨C2664.

解决方法是传递一个指针,该指针存储在一个不会被GC移动的内存位置.这样的位置很容易得到,本地变量有资格.它存储在堆栈中,不会被移动.所以让它看起来像这样:

void Connect()
{
    ServerInterface temp;
    GetServerInterface(&temp);
    this->_serverInterface = temp;
    // etc..
}
Run Code Online (Sandbox Code Playgroud)

您已经发现自己,只是不要忘记分配班级成员.

  • 我第一次得到了,但你的第二次评论让我有点困惑:)哦,好吧...... (2认同)