2011-05-26 68 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