我试图使用一个函数调用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编写的,为什么他们会在这些参数上使用@运算符? 我错过了什么?
你的两个变量PropertyRegDataType
和RequiredSize
都应该声明为DWORD
。 您实际上将RequiredSize
声明为Cardinal
尽管这是等同的。
你是正确的,因为他们是var
参数,你不应该包括@
地址运算符。
很难说为什么你得到的错误消息,而不知道你通过其他参数。
编辑
正如评论家所指出的那样,JEDI的翻译是不正确的, PropertyRegDataType
,因为它是一个可选参数,应该通过值传递,并输入PDWORD
这样你就可以传递nil
。
Delphi通过var
和out
关键字支持“引用参数”,在一些API转换中,类似C的指针可以被这个约定替代; 这些参数是强制性的,必须按原样传递,而不是地址运算符@
。
如果参数声明保留为指针,允许通过nil
, 则必须确保该参数是可选的 – 或者 – 通过@
运算符将其设置为合适大小的有效内存内存位置; 在这种情况下不执行类型检查 。