在Delphi的Windows API参数 – 传递var参数有或没有@运营商?

我试图使用一个函数调用SetupDiGetDeviceRegistryProperty与delphi7.该调用是从示例函数SetupEnumAvailableComPorts 。 它看起来像这样:

SetupDiGetDeviceRegistryProperty( DevInfoHandle, DeviceInfoData, RegProperty, @PropertyRegDataType, nil, 0, @RequiredSize ); 

我在参数@PropertyRegDataType和@RequiredSize上收到错误“实际和forms参数的types必须相同”。 这些参数被声明:

 var RequiredSize: Cardinal; PropertyRegDataType: DWORD; 

MSDN将这些参数描述为: “RequiredSize [out,optional]指向DWORDtypesvariables的指针,该variables接收所需大小(以字节为单位)的PropertyBuffer缓冲区,该缓冲区用于保存请求属性的数据。并且可以为NULL。 “和”PropertyRegDataType [out,optional]指向一个variables的指针,该variables接收正在检索的属性的数据types,这是标准的registry数据types之一,该参数是可选的,可以是NULL “。

SetupDiGetDeviceRegistryProperty(来自JVCL的 SetupAPI.pas中)的声明如下所示:

 function SetupDiGetDeviceRegistryProperty( DeviceInfoSet: HDEVINFO; const DeviceInfoData: TSPDevInfoData; Property_: DWORD; var PropertyRegDataType: DWORD; PropertyBuffer: PBYTE; PropertyBufferSize: DWORD; var RequiredSize: DWORD ): BOOL; stdcall; {$EXTERNALSYM SetupDiGetDeviceRegistryProperty} 

由于PropertyRegDataType和RequiredSize是var参数,因此应该能够在不使用@运算符的情况下传递。 实际上,如果我从函数调用参数中删除了@操作符,代码将会编译,但是会与访问冲突(读取地址0)一起崩溃。 原来的代码是为Delphi 7编写的,为什么他们会在这些参数上使用@运算符? 我错过了什么?

你的两个变量PropertyRegDataTypeRequiredSize都应该声明为DWORD 。 您实际上将RequiredSize声明为Cardinal尽管这是等同的。

你是正确的,因为他们是var参数,你不应该包括@地址运算符。

很难说为什么你得到的错误消息,而不知道你通过其他参数。

编辑

正如评论家所指出的那样,JEDI的翻译是不正确的, PropertyRegDataType ,因为它是一个可选参数,应该通过值传递,并输入PDWORD这样你就可以传递nil

Delphi通过varout关键字支持“引用参数”,在一些API转换中,类似C的指针可以被这个约定替代; 这些参数是强制性的,必须按原样传递,而不是地址运算符@
如果参数声明保留为指针,允许通过nil则必须确保该参数是可选的 – 或者 – 通过@运算符将其设置为合适大小的有效内存内存位置; 在这种情况下不执行类型检查