将C声明转换为Delphi XE2
我在将一些C声明转换为Delphi XE2以调用DLL中的函数时遇到问题。我翻译了Visual Basic源文件中的所有函数声明,但在测试它们时遇到了问题。有些函数返回长值,但在调试代码时,我发现这些函数返回的值不正确。然后我转向C中的原始代码,在那里我找到了问题的根源:在原始C代码中的某个地方有这样一个声明:将C声明转换为Delphi XE2,c,delphi,pointers,dll,opaque-pointers,C,Delphi,Pointers,Dll,Opaque Pointers,我在将一些C声明转换为Delphi XE2以调用DLL中的函数时遇到问题。我翻译了Visual Basic源文件中的所有函数声明,但在测试它们时遇到了问题。有些函数返回长值,但在调试代码时,我发现这些函数返回的值不正确。然后我转向C中的原始代码,在那里我找到了问题的根源:在原始C代码中的某个地方有这样一个声明: typedef struct { } __RSI_CHANNEL; typedef __RSI_CHANNEL FAR* RSI_CHANNEL; 现在,一些函数返回RS
typedef struct { } __RSI_CHANNEL;
typedef __RSI_CHANNEL FAR* RSI_CHANNEL;
现在,一些函数返回RSI_通道;这些函数返回如下值:
return (RSI_CHANNEL)ws;
Type
RSI_CHANNEL = Pointer;
...{ later in implementation block }...
Function rsiInitWsock(HostName : PAnsiChar; port : Long) : RSI_CHANNEL; stdcall; external 'rsidll32';
ws声明为:
rsiChannel FAR* ws = new FAR rsiChannel;
rsiChannel是一个typedef结构。到目前为止,一切都很好……到现在为止,我想你们中的一些人可能已经认识到这是PIMPL习语。好的,根据源代码注释,我应该保存该返回值(RSI_通道)并针对NULL进行测试,然后通过函数调用传递它,不做任何改动……所以我认为它应该作为指针在Delphi中实现。但它不起作用。大概是这样的:
return (RSI_CHANNEL)ws;
Type
RSI_CHANNEL = Pointer;
...{ later in implementation block }...
Function rsiInitWsock(HostName : PAnsiChar; port : Long) : RSI_CHANNEL; stdcall; external 'rsidll32';
没有编译错误,没有运行时错误。如果我调用这个函数,我得到零
?知道如何在Delphi XE2中实现这一点吗?还有,我做错了什么?提前谢谢
其他详情:
- Delphi XE2(目标:Win32)
- Windows 7 x64
我发现了问题;这与我的代码无关,它从一开始就是正确的;它与DLL中的ping函数有关,它在笔记本电脑上工作,但不想在台式电脑上工作(都是Win7),当它不工作时,它会中断对DLL的后续函数调用(为什么,我还不知道…)。无论如何,这不是一个完整的解决方案,但是@DavidHeffernan是第一个想到问题出在其他地方的人,所以我接受他的答案主要是因为它为我指明了正确的方向。谢谢大家 如上所述,您对RSI_频道的处理是正确的。将其声明为
指针
是适当的操作。要增强类型安全性,可以定义不同的类型而不是别名:
Type
RSI_CHANNEL = type Pointer;
如果port
参数实际上是WORD
,那么它将映射到Delphi中的WORD
至于你的问题,它在别处。RSI_频道的翻译是准确的 由于
RSI_CHANNEL
是C代码中的类型化指针,我将在Delphi中声明一个类似类型的指针进行匹配,而不是使用非类型化的指针
(这也与现代Delphi版本相一致,使用STRICT
,以避免Win32 API句柄类型中的非类型指针,如HWND
,等等):
rsinitwsock
的C声明是什么样子的?它被声明为:RSI_DLL RSI_CHANNEL RSI_API rsinitwsock(char*hostname,WORD port);RSI_DLL是用于DLL中导出函数的宏,RSI_API=stdcall。我认为WORD
->UInt16
,不是吗?您正在声明long
,它是一个有符号的64位整数。@J。。。只有在C#中是long
64位wide@DavidHeffernan实际上我只是想知道我是否有交叉线,它可能是32位的。。。我总是在delphi中使用Int64
——无数的别名让我大吃一惊!在任何情况下,它都不是无符号的,也不是16位字
。我应该补充一点,我尝试了几个选项……所有基于指针的选项都返回了Nil。由于VB实现使用Long作为返回类型,所以在看到C声明之前,我一直使用基于整数的类型。有趣的是,当我使用Int64(和UInt64)作为返回类型时,我得到了一些东西(一个大数字),其他所有东西都得到了0或Nil。Int64是错误的,因为指针是32位的。问题出在别处。如果使用Int64
,编译器将期望函数使用EDX和EAX寄存器返回64位值,然后将它们组合在一起以创建Int64
值。但32位环境中的指针将仅使用EAX寄存器返回,使EDX寄存器未使用或更糟的情况下为随机。这将导致大量的Int64
值被“返回”。那么问题就出在别处,与指针本身无关。您必须调试到DLL函数调用中,并准确地找出它真正返回的内容以及它是如何返回的。有些可疑的事情正在发生。您显示的代码不应该以您描述的方式运行。@Remy这些注释是问题的焦点,应该出现在答案中。