2011-05-26 101 views
2

我已經爲原生C++ dll編寫了C++/Cli包裝器,但是當我從C#調用一些方法時,我的C++/Cli包裝器DLL中出現System.AccessViolationException錯誤!有必要編組非託管類型或其他東西?!原生C++ dll的C++/CLI包裝器

// Wrapper.h 

typedef UnmanagedClass* (*Instance)(void); 

private: 
    UnmanagedClass *m_object; // unmanaged object 

// Wrapper.cpp 

Wrapper:Wrapper() 
{ 
    HINSTANCE unmanagedLib; 
    unmangedLib = LoadLibrary(SystemStringToLPCSTR(dllPath+dllName)); 

    // load instance 
    Instance _createInstance = (Instance)GetProcAddress(unmangedLib, "GetInstance"); 
    m_object = (_createInstance)(); 
} 

Wrapper::~Wrapper() 
{ 
    m_object->~UnmanagedClass(); 
} 


Uint32 Wrapper::SomeMethod(Uint8 *bytRecvBuffer, int &iRecvLen) 
{ 
    return m_object->SomeMethod(bytRecvBuffer, iRecvLen); 
} 

// Unmanaged Class 

class UnmanagedClass  
{ 
public: 
    /** 
    * Default constructor. 
    */ 
    UnmanagedClass(void); 
    /** 
    * Default Destructor 
    */ 
    ~UnmanagedClass(void); 

    virtual Uint32 Wrapper::SomeMethod(Uint8 *bytRecvBuffer, int &iRecvLen); 
}; 

// export the UnmanagedClass object 
extern "C" _declspec(dllexport) UnmanagedClass* GetInstance(); 

// UnamangedClass.cpp 

UnamangedClass::~UnamangedClass(void) 
{ 
    if (UnamangedClassDLL != NULL) 
     FreeLibrary(UnamangedClassDLL); 

    UnamangedClassDLL = NULL; 
} 

extern "C" _declspec(dllexport) UnmanagedClass* GetInstance() 
{ 

    return new UnmanagedClass(); 
} 

當我打電話從C#示例的someMethod我得到的錯誤在C++/CLI的dll! (我包括在C sharp項目中添加參考的C++/cli dll並創建包裝對象)

謝謝你的幫忙!

迎接

+0

'有必要對非託管類型或其他東西進行編組?'我們如何知道何時不顯示'UnmanagedClass'或'Wrapper'的定義? (順便說一下,'m_object->〜UnmanagedClass();'看起來絕對錯誤。) – ildjarn 2011-05-26 08:02:16

+0

我不認爲這是錯誤的(請閱讀http://ondotnet.com/lpt/a/4731 - >我寫封裝本教程) – leon22 2011-05-26 08:04:56

+0

@ leon22:同樣,我們無法確定,因爲我們看不到'UnmanagedClass'和'Wrapper'的定義。 – ildjarn 2011-05-26 08:06:06

回答

0

我發現錯誤(System.AccessViolationException):

我使用的是其他物體的非託管代碼沒有初始化(空對象 - >僅申報)!

使用new()初始化對象,並且所有對象都應該正常運行!

2

這是不合適的直接調用,將​​其用(非配置)new分配對象的析構函數。嘗試改變

m_object->~UnmanagedClass(); 

delete m_object; 
m_object = 0; 

m_object = 0;是必要的,因爲不像本地C++類的析構函數,這可能只會被調用一次,一個管理型的Dispose實現可以重複調用,這樣做必須已定義的行爲)。

或者,更好的是,除了公開GetInstance函數之外,還公開了DestroyInstance函數並調用該函數而不是使用delete,因此消費代碼不需要依賴於GetInstance的實現細節(即,它使用operator new分配其實例)。

+0

謝謝,但是爲什麼我在調用方法時會遇到System.AccessViolationException異常? – leon22 2011-05-26 08:23:54

+0

@ leon22:在我輸入對此的回覆之前,看看是否有幫助。; - ] – ildjarn 2011-05-26 08:25:55

+0

我不這麼認爲,因爲我沒有調用析構函數:m_object-> SomeMethod()(但你是對的,它是更好的方法來破壞對象) – leon22 2011-05-26 08:37:27