2009-02-20 99 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; 
} 
相關問題