2009-02-20 98 views
5

我正在创建一个依赖于众多C++静态库的C++/CLI包装器DLL。一些函数调用需要传入非托管指针。我如何正确传递它们?在C++/CLI中传递非托管指针

此外,其他函数期望“this pointer”作为void *传入。什么是通过“这个”的正确途径?

这里是我的类定义...

public ref class RTPClient 
{ 
    public: 
     RTPClient(); 
     ~RTPClient(); 

     bool Connect(); 
     void Disconnect(); 

    private: 
     CIsmaClient* mClient; 
}; 

这里是我的使用,其中有问题的指针被用来...

RTPClient::RTPClient(): 
    mClient(NULL) 
{ 
    CIsmaClient::Create(&mClient, NULL, &AllocBuffer, &GetDataPointer, this); 
} 

&和移动客户端的使用“此“导致以下编译器错误... 1>。\ VBLoadSimulatorDll.cpp(40):错误C2664:'CIs maClient ::创建”:不能从转换参数1 'CLI :: interior_ptr' 到 'CIsmaClient **' 1>使用 1> [ 1>类型= CIsmaClient * 1>]

1> \。 VBLoadSimulatorDll.cpp(40):错误C2664:'CIsmaClient :: Create':无法将参数5从'VBLoadSimulator :: RTPClient^const'转换为'VOID *'

回答

9

如果您正在传递指向托管类的指针,很容易将^参考转换为指针,但必须固定管理对象,以便GC不会将其移动到内存中(从而使指针无效)

这是pin_ptr

简单但是你的代码是做两件事情,这将无法正常工作

RTPClient::RTPClient(): 
     mClient(NULL) 
{ 
    CIsmaClient::Create(
     &mClient,   // 1 
     NULL, 
     &AllocBuffer, 
     &GetDataPointer, 
     this);   //2 
} 

1)你试图把托管堆上(的的位置的东西地址指针指向mClient在托管堆上。因此它可以在内存中移动,因此编译器供应商内部指针(其值通过GC操作来维护)。这需要是pinned,这只有在Create函数不希望在范围结束后使用指针(如果它将其传递到其他任何位置以存储它将导致错误)时才会起作用。

2)你通过了一个handle(滑稽的帽子符号),而不是一个指针。 (请阅读维基百科关于它们的章节,它们是一个很好的概述)这不是(也不能)被非托管代码所理解。

在这种情况下,我可以考虑这个参数的唯一原因是作为一个显式的状态变量传递给后续的函数回调(如果我错了,请纠正我)。在这种情况下,'this'永远不会正常工作,因为一旦pin_ptr超出范围,它可以在内存中移动。

考虑到这一点,这里是一个(部分)纠正的实现,明确什么可以修复和不能修复。

RTPClient::RTPClient(): 
     mClient(NULL) 
{ 
    // make it clear you want the address of the instance variable 
    pin_ptr<CIsmaClient*> pinnedClient = &this->mClient; 
    CIsmaClient::Create(
     pinnedClient,   // fixed 
     NULL, 
     &AllocBuffer, 
     &GetDataPointer, 
     x /* pass something else in */);   //2 
} 

如果你提供什么最后一个参数用于我可以建议可能的解决方案

+0

这里是正确的链接: http://msdn.microsoft.com/en-us/library/1dz8byfh.aspx – 2009-02-20 14:39:03

+0

的指针是,虽然非受管类... – cjserio 2009-02-20 14:44:49

2

我想你会认为这是通过一个空指针传递一个托管引用的最简单的方法的详细信息:

void SomeFunction(void* input) 
{ 
    gcroot<ManagedClass^>* pointer = (gcroot<ManagedClass^>*)(input); 
    (*pointer)->ManagedFunction(); 
} 

void Example() 
{ 
    ManagedClass^ handle = gcnew ManagedClass(); 
    gcroot<ManagedClass^>* pointer = new gcroot<ManagedClass^>(handle); 
    SomeFunction((void*)pointer); 
    delete pointer; 
} 
相关问题