我目前正在用 C++/CLI 编写一个 DLL,它将充当非托管程序和另一个 C# DLL 之间的“代理”。调用程序需要我的“代理 DLL”来实现将由非托管程序调用的各种过程。到目前为止,没问题。
但是:其中一个函数具有以下原型(prototype):
extern "C" __declspec ( dllexport ) long Execute(unsigned long command, long nInBytes, byte bInData[], long nOutBytes, long* pnUsedOutBytes, byte bOutData[])
好吧,我的代理 DLL 只是调用提供以下函数原型(prototype)的 C# DLL(调用程序的文档也给出了它):
unsafe public UInt32 Execute(UInt32 command, Int32 nInBytes, byte* pInData, Int32 nOutBytes, Int32* pnUsedOutBytes, byte* pOutData);
编译器在参数 5 pnUsedOutBytes
处抛出错误 (C2664) 并告诉我,long*
无法转换为 int*
。好吧,long
和 int
目前有相同的实现,可能会在未来的某个时候改变,所以抛出的错误是可以理解的(尽管非指针 long 使用确实不抛出错误?)。
回到实际问题:调用我的 C# 函数的最佳解决方案是什么?我已经读过(当然)最好的解决方案是在调用 .NET 函数时使用 .NET 类型。所以:在调用函数时进行简单的类型转换是否安全,或者在任何不好的情况下这种类型转换都不起作用?
使用这一行可以让编译器冷静下来,但它真的安全吗?
curInstance->Execute(command, nInBytes, pInData, nOutBytes, (System::Int32*)pnUsedOutBytes, pOutData);
提前致谢!
最佳答案
不,不要使用那个类型转换。假设 pnUsedOutBytes
的实际值大于 2^32。最好的情况是,对 Execute
的调用会覆盖低字节并保留高于 32 位的位,从而导致错误的答案。
解决方案是使用指向 32 位数据类型的指针调用 Execute
。在您的代理中创建一个,如果需要,给它一个合理的起始值,进行调用,并将结果值复制到 pnUsedOutBytes
指向的 long
中。
哦,不要解释错误信息。错误信息没有说你不能cast long*
to int*
;你可以。几乎可以肯定的是,编译器无法将 long*
convert 为 int*
。没错:这两种类型之间没有隐式 转换。添加强制转换告诉编译器去做;这样你就有了一个显式转换。
关于c# - 将 (V)C++ long* 转换为 C# Int32* 的安全方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19496526/