1

我目前正在用 C++/CLI 编写一个 DLL,它将充当非托管程序和另一个 C# DLL 之间的“代理”。调用程序需要我的“代理 DLL”来实现将由非托管程序调用的各种过程。到目前为止,没有问题。

但是:其中一个函数具有以下原型:

extern "C" __declspec ( dllexport ) long Execute(unsigned long command, long nInBytes, byte bInData[], long nOutBytes, long* pnUsedOutBytes, byte bOutData[])

好吧,我的代理 DLL 只是调用了 C# DLL,它提供了以下函数原型(调用程序的文档也给出了它):

unsafe public UInt32 Execute(UInt32 command, Int32 nInBytes, byte* pInData, Int32 nOutBytes, Int32* pnUsedOutBytes, byte* pOutData);

编译器在参数 5 处抛出一个错误(C2664)pnUsedOutBytes并告诉我,long*不能强制转换为int*. 好吧,longint有相同的实现,将来可能会改变,所以抛出的错误是可以理解的(尽管非指针长时间使用不会抛出错误?)。

回到实际问题:调用我的 C# 函数的最佳解决方案是什么?我已经读过(当然)最好的解决方案是在调用 .NET 函数时使用 .NET 类型。所以:在调用函数时进行简单的类型转换是否安全,或者在任何这种类型转换不起作用的糟糕情况下可能会出现这种情况?

使用这条线可以让编译器平静下来,但它真的安全吗?

curInstance->Execute(command, nInBytes, pInData, nOutBytes, (System::Int32*)pnUsedOutBytes, pOutData);

提前致谢!

4

2 回答 2

0

最简单的解决方案就是修复导出函数的签名:

extern "C" __declspec ( dllexport ) int32_t Execute(uint32_t command, int32_t nInBytes, byte bInData[], int32_t nOutBytes, int32_t* pnUsedOutBytes, byte bOutData[])

LoadLibraryint32_t不会让您对andint和之间的区别感到悲伤long,因为它们都是 32 位整数类型。

(实际上,LoadLibrary也不会让您为一堆实际错误感到悲伤,......但在这种情况下,您没有使用不兼容的类型)

于 2013-10-21T14:22:46.133 回答
0

不,不要使用那个演员表。假设实际值pnUsedOutBytes大于 2^32。最好的情况是,调用Execute将覆盖低字节并单独保留高于 32 的位,从而导致错误答案。

Execute解决方案是使用指向 32 位数据类型的指针进行调用。在您的代理中创建一个,如果需要,给它一个合理的起始值,进行调用,并将结果值复制到指向的long那个。pnUsedOutBytes

哦,不要解释错误消息。错误消息没有你不能投到 long*; int*你可以。它几乎可以肯定地说编译器无法转换 long*int*. 没错:这两种类型之间没有隐式转换。添加演员表告诉编译器这样做;这样你就有了一个明确的转换。

于 2013-10-21T14:13:51.263 回答