有很多API例程将指向某个变量的指针作为转换为var参数的参数,但可以根据Windows帮助文件指定为nil指针.
例如,ChangeDisplaySettings函数声明为:
function ChangeDisplaySettings(var lpDevMode: TDeviceMode; dwFlags: DWORD): Longint; stdcall;
Run Code Online (Sandbox Code Playgroud)
但Windows帮助文件明确指出"在动态模式更改后,为lpDevMode参数传递NULL是返回默认模式的最简单方法." 正确的翻译应该是:
function ChangeDisplaySettings(lpDevMode: PDeviceMode; dwFlags: DWORD): Longint; stdcall;
Run Code Online (Sandbox Code Playgroud)
我发布这个问题和答案,以帮助新手解决这些问题,而无需重新声明功能.我还记得在开始时这对我来说是一个问题.
Jan*_*ber 12
一种解决方案是使用指针代替var参数重新声明任何此类函数,但有一个更简单的解决方案.只需将解除引用的nil指针强制转换为正确的类型,例如,对于ChangeDisplaySettings示例,使用以下命令将显示模式重置为默认注册表设置:
ChangeDisplaySettings(TDeviceMode(nil^), 0);
Run Code Online (Sandbox Code Playgroud)
要么
ChangeDisplaySettings(PDeviceMode(nil)^, 0);
Run Code Online (Sandbox Code Playgroud)
这样你传递一个恰好位于内存地址为零的var参数 - 编译器很高兴你可以将一个nil指针传递给API例程!
编辑:从David Hefferman的评论来看,标准做法似乎是重新声明这样的例程.就个人而言,我更喜欢使用标准声明,如果我可以在我自己的个人单位,但出于专业工作的目的,我建议开发人员遵循标准做法.
除了其他有用的答案和评论之外,我还有另外一点.在这种情况下,从标题中翻译此API的任何人都没有仔细查看API文档.如果他们这样做了,很明显传递"nil"是一件有效的事情.
在这种情况下,正确的行动方针是声明一组引用相同导入的重载.一个是漂亮的"var"参数版本,另一个是"指向结构的指针"版本.这样可以使你可以直接传入一个TDeviceMode变量(不需要获取var的地址),并在必要时传递nil.编译器将"nil""匹配"到指向结构的指针,然后引用该指针.由于两个API都解析为相同的API,并且传递参数的实际方式没有区别,因此一切仍然按预期工作.
因为当你应该能够传递一个API翻译错误的"nil"时,没有该API的重载版本.请随时在http://quality.embarcadero.com的报告中注明.
为了记录,我多年来在产品中做了很多API翻译......当然可以想象我是一个愚蠢的开发人员没有对这个进行适当的研究:).
归档时间: |
|
查看次数: |
1232 次 |
最近记录: |