Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将C声明转换为Delphi XE2_C_Delphi_Pointers_Dll_Opaque Pointers - Fatal编程技术网

将C声明转换为Delphi XE2

将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

我在将一些C声明转换为Delphi XE2以调用DLL中的函数时遇到问题。我翻译了Visual Basic源文件中的所有函数声明,但在测试它们时遇到了问题。有些函数返回长值,但在调试代码时,我发现这些函数返回的值不正确。然后我转向C中的原始代码,在那里我找到了问题的根源:在原始C代码中的某个地方有这样一个声明:

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这些注释是问题的焦点,应该出现在答案中。