我正在尝试调用IsNativeVhdBoot函数,但收到错误消息The parameter is incorrect.
function IsNativeVhdBoot(var NativeVhdBoot:PBOOL):BOOL; external Kernel32 name 'IsNativeVhdBoot';
function _IsNativeVhdBoot:Boolean;
var
pB:PBOOL;
begin
Result := False;
if IsNativeVhdBoot(pB) then
Result := pB^
else RaiseLastOSError;
end;
我也试过这样称呼
function __IsNativeVhdBoot: Boolean;
type
TIsNativeVhdBoot = function(
var NativeVhdBoot: pBOOL
): BOOL; stdcall;
var
bNativeVhdBoot: pBOOL;
NativeVhdBoot : TIsNativeVhdBoot;
begin
Result := False;
NativeVhdBoot := GetProcAddress(GetModuleHandle(kernel32), 'IsNativeVhdBoot');
if (@NativeVhdBoot <> nil) then
begin
if not NativeVhdBoot(bNativeVhdBoot) then
RaiseLastOSError;
Result := bNativeVhdBoot^;
end
else
RaiseLastOSError;
end;
我的问题是
function Foo():BOOL; external Kernel32 name 'Foo';
和type TFoo = function(): BOOL; stdcall;
因为我通常像第一种方法那样进行调用,但是当我得到上述错误信息时,我搜索了如何调用外部函数,我找到了另一种方法。
更新
在C ++中测试了相同的函数,我得到了同样的错误,我的代码如下
#include "stdafx.h"
#include "Windows.h"
int _tmain(int argc, _TCHAR* argv[])
{
BOOL Result = false;
SetLastError(0);
if (IsNativeVhdBoot(&Result)) {
if (Result) {
printf_s("Running inside VHD\n");
}
else
printf_s("Running inside physical disk drive\n");
}
else
printf("IsNativeVhdBoot failed with error %d.\n", GetLastError());
return 0;
}
答案 0 :(得分:5)
在您的第一次尝试中,您的调用约定不匹配,您链接的文档将其声明为“stdcall”。但是,从问题和答案的评论看来,这并不是你得到“参数不正确”错误的原因。该调用似乎在所有条件下都设置了此错误。
在两次尝试中,您的参数都有额外的间接级别。该文档指出API期望BOOL变量的地址。该参数的解释实际上与文档中的声明不一致,该声明建议指向BOOL的指针。但是,'winbase.h'中的实际声明与文档中的声明不同,并且符合措辞:
WINBASEAPI
BOOL
WINAPI
IsNativeVhdBoot (
_Out_ PBOOL NativeVhdBoot
);
因此参数是'var BOOL'或'PBOOL',而不是'var PBOOL'。如果你使用'PBOOL',你必须传递一个现有的BOOL变量的地址,而不是指向你的第一个片段中没有指向任何地方的指针。
此时应注意,它实际上并不重要,因为API似乎没有设置'out'参数。这可能有点预期,因为文档令人困惑,因为它声明结果将被设置为参数,并将作为函数结果返回。这很不寻常......
请注意,根据文档,函数的返回值并不表示函数失败或成功。这本身是不一致的,因为文档也建议调用GetLastError
,通常只在函数失败时调用GetLastError
,这里我们无法在调用它之前知道它是否失败。在任何情况下,暗示是您必须删除在错误返回时引发异常的语句。
对于第二个问题,您的第一个声明静态加载库,第二个片段动态加载库。有关更多信息,请参阅documentation。如上所述,您还有一个额外的区别,即第一个具有寄存器调用约定,但这种差异并不意味着。