如何将nil传递给var参数?

时间:2015-11-22 21:17:13

标签: delphi delphi-7

有很多API例程将指向某个变量的指针作为转换为var参数的参数,但可以根据Windows帮助文件指定为nil指针。

例如,ChangeDisplaySettings函数声明为:

function ChangeDisplaySettings(var lpDevMode: TDeviceMode; dwFlags: DWORD): Longint; stdcall;

但Windows帮助文件明确指出“在动态模式更改后,为lpDevMode参数传递NULL是返回默认模式的最简单方法。”正确的翻译应该是:

function ChangeDisplaySettings(lpDevMode: PDeviceMode; dwFlags: DWORD): Longint; stdcall;

我发布这个问题并回答帮助新手解决这些问题,而无需重新声明这些功能。我仍然记得在开始时这对我来说是一个问题。

2 个答案:

答案 0 :(得分:12)

一种解决方案是使用指针代替var参数重新声明任何此类函数,但有一个更简单的解决方案。只需将解除引用的nil指针强制转换为正确的类型,例如,对于ChangeDisplaySettings示例,使用以下命令将显示模式重置为默认注册表设置:

ChangeDisplaySettings(TDeviceMode(nil^), 0);

ChangeDisplaySettings(PDeviceMode(nil)^, 0);

这样你就传递一个恰好位于内存地址为零的var参数 - 编译器很高兴你可以将一个nil指针传递给API例程!

编辑:根据David Hefferman的评论,似乎标准做法是重新声明此类例程。就个人而言,我更喜欢使用标准声明,如果我可以在我自己的个人单位,但出于专业工作的目的,我建议开发人员遵循标准做法。

答案 1 :(得分:6)

除了其他有用的答案和评论之外,我还有另一个问题。在这种情况下,从标题中翻译此API的任何人都没有仔细查看API文档。如果他们这样做了,那就明白过去" nil"是一件有效的事情。

在这种情况下,正确的做法是声明一组引用相同导入的重载。一个是好的" var"参数版本和另一个将是"指向结构的指针"版。这样可以使你可以直接传入一个TDeviceMode变量(不需要获取var的地址),并在必要时传递nil。编译器将匹配" " nil"指向结构的指针,然后被引用。由于两个API都解析为相同的API,并且参数传递的实际方式不同,所以一切仍然按预期工作。

因为当你应该能够传递一个" nil"时,不存在该API的重载版本。这是一个API转换错误。请随时在http://quality.embarcadero.com的报告中说明这一点。

为了记录,我多年来在产品中做了很多API翻译......当然可以想象,是一个愚蠢的开发者,他没有做过对此进行适当的研究:)。

相关问题