【发布时间】:2012-02-15 21:09:14
【问题描述】:
我是一位经验丰富的软件工程师,但对 C# 有点陌生。我有一个 DLL,它由具有 C 接口的 C++ 对象组成,如图所示。我使用这个 C 接口是因为我不确定是否有办法从我的 C# 应用程序访问 DLL 中的 C++ 入口点。
__declspec(dllexport) void *Constructor();
__declspec(dllexport) void Destructor(void *pObj);
__declspec(dllexport) int Method(void *pObj, char *pSrcDst, int len);
这是上面接口的C代码。
extern "C" void *Constructor()
{
return (void *)new Object;
}
extern "C" void Destructor(void *pObj)
{
delete (Object *)pObj;
}
extern "C" int Method(void *pObj, char *pSrcDst, int len)
{
if (!pObj) return 0;
return ((Object *)pObj)->Method(pSrcDst, len);
}
到目前为止一切顺利。现在,我需要能够从 C# 应用程序访问此接口。据我所知,我已经实现了以下 C# 接口。
unsafe public class Wrapper
{
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("MyDLL.dll")]
public static extern
IntPtr Constructor();
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("MyDLL.dll")]
public static extern
void Destructor(IntPtr pObj);
[SuppressUnmanagedCodeSecurityAttribute()]
[DllImport("MyDLL.dll")]
public static extern
int Method(IntPtr pObj, [In,Out] byte[] pSrcDst, int len);
这是使用上述接口的 C# 代码。
private IntPtr pObject;
public object()
{
pObject = Wrapper.Constructor();
}
~object()
{
Wrapper.Destructor(pObject);
}
public override byte[] method()
{
byte[] bytes = new byte[100];
int converted = Wrapper.Method(pObject, bytes, bytes.length);
return bytes;
}
代码在调用 Wrapper.Method 和 Wrapper.Destructor 时都断言。我假设我没有正确处理指向对象的指针。有什么建议吗?
【问题讨论】:
-
“代码断言”是什么意思?你收到一些错误信息吗?
-
是的,“检测到 PInvokeStackImbalance”。
-
请记住,大多数编译器假定
extern "C"函数不会引发异常(尤其是在 C 代码调用它们的情况下),因此您需要确保包装new Object()位在异常块中以防止任何异常(特别是std::bad_alloc)转义。 -
旁注:您不需要为每个函数重复 extern "C"。您可以将它们全部包装在 extern "C" { /*functions here*/ } 的范围内