将(V)C ++ long *转换为C#Int32 *的安全方法?

时间:2013-10-21 13:56:26

标签: c# c++ c++-cli

我目前正在用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 pnUsedOutBytes处抛出错误(C2664)并告诉我,long*无法转换为int*。好的,longint当前具有相同的实现,可能会在将来某个时候发生变化,因此抛出的错误是可以理解的(尽管非指针长期使用不会引发错误?)

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

使用这一行可以使编译器平静下来,但是它真的安全吗?

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

提前致谢!

2 个答案:

答案 0 :(得分:0)

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

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

哦,不要解释错误信息。错误消息表示您无法强制转换 long*int*;您可以。几乎可以肯定的是,编译器无法 long*转换为int*。这是正确的:两种类型之间没有隐式转换。添加转换会告诉编译器执行此操作;你有一个明确的转换。

答案 1 :(得分:0)

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

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

LoadLibrary不会对int32_tintlong之间的区别产生任何不满,因为它们都是32位整数类型。

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