我试图在delphi上使用Windows API的函数,Windows Wlanapi的函数.dll(Native WIFI API(
无线打开手柄
DWORD WINAPI WlanOpenHandle(
__in DWORD dwClientVersion,
__reserved PVOID pReserved,
__out PDWORD pdwNegotiatedVersion,
__out PHANDLE phClientHandle
);
WLAN托管网络查询属性
DWORD WINAPI WlanHostedNetworkQueryProperty(
__in HANDLE hClientHandle,
__in WLAN_HOSTED_NETWORK_OPCODE OpCode,
__out PDWORD pdwDataSize,
__out PVOID *ppvData,
__out PWLAN_OPCODE_VALUE_TYPE *pWlanOpcodeValueType,
__reserved PVOID pvReserved
);
我尝试使用此函数和其他函数数小时,阅读 MSDN 参考和其他站点,但我无法正常工作。
我的尝试
type
TWlanOpenHandle = function( dwClientVersion:DWORD;
pReserved:Pointer;
pdwNegotiatedVersion:PDWORD;
phClientHandle:PHANDLE
):DWORD; stdcall;
function apiWlanOpenHandle( dwClientVersion:DWORD;
pReserved:Pointer;
pdwNegotiatedVersion:PDWORD;
phClientHandle:PHANDLE
):DWORD;
implementation
function apiWlanOpenHandle ( dwClientVersion:DWORD; pReserved:Pointer; pdwNegotiatedVersion:PDWORD; phClientHandle:PHANDLE ):DWORD;
var
WlanOpenHandle: TWlanOpenHandle;
DLL: Cardinal;
begin
DLL:=LoadLibrary('Wlanapi.dll');
WlanOpenHandle := GetProcAddress(DLL, 'WlanOpenHandle');
if Assigned(WlanOpenHandle) then
begin
WlanOpenHandle(dwClientVersion, pReserved, pdwNegotiatedVersion, phClientHandle);
end
else begin
ShowMessage('Function not found');
end;
end;
我正在尝试翻译这个 API,似乎有很多工作,我只是 delphi 的初学者,我在网上阅读了很多东西,我如何处理这个OpCode
参数,似乎是一个带有常量的 C 结构,PWLAN_OPCODE_VALUE_TYPE?
http://msdn.microsoft.com/en-us/library/windows/desktop/dd439502(v=vs.85(.aspx
你实际上并没有展示你是如何称呼apiWlanOpenHandle
的,我认为,这可以解释问题是什么。但是,有一个非常常见的错误很可能使您感到困惑。
考虑 API 的 C 声明:
DWORD WINAPI WlanOpenHandle(
__in DWORD dwClientVersion,
__reserved PVOID pReserved,
__out PDWORD pdwNegotiatedVersion,
__out PHANDLE phClientHandle
);
我怀疑给您带来问题的参数是最后两个。让我们考虑一下pdwNegotiatedVersion
.这是指向DWORD
的指针。由于这是一个 out 参数,因此必须提供指向有效内存的指针。我怀疑您只是在声明一个 PDWORD
类型的变量并传递它。
var
NegotiatedVersionPtr: PDWORD;
begin
WlanOpenHandle(...., NegotiatedVersionPtr, ...);
然后WlanOpenHandle
该函数取消引用该指针并尝试写入内存。如果您没有给出有效的指针,那么这将失败。
天真的解决方案是将调用代码更改为如下所示:
var
NegotiatedVersion: DWORD;
NegotiatedVersionPtr: PDWORD;
begin
NegotiatedVersionPtr := @NegotiatedVersion;
WlanOpenHandle(...., NegotiatedVersionPtr, ...);
这将起作用,但有一种更清洁的方法。像这样声明 API 导入:
function WlanOpenHandle(
dwClientVersion: DWORD;
pReserved: Pointer;
out NegotiatedVersion: DWORD;
out ClientHandle: THandle
): DWORD; stdcall; external 'Wlanapi.dll';
类型 DWORD
的 out
参数实际上作为指针传递到您作为函数调用的参数提供的DWORD
。然后,可以将调用代码更改为如下所示:
var
ReturnValue: DWORD;
NegotiatedVersion: DWORD;
ClientHandle: THandle;
begin
ReturnValue := WlanOpenHandle(2, nil, NegotiatedVersion, ClientHandle);
if ReturnValue<>ERROR_SUCCESS then
//respond to error
请注意,我还添加了一些您确实应该执行的错误检查。
使用 指针声明 Windows API 函数的原因是 C 语言仅支持按值传递参数。它根本没有通过引用传递,即 out
或var
德尔菲术语。支持按引用传递的语言应尽可能使用它们。
某些 Windows API 函数将可选参数声明为指针。在这种情况下,传递NULL
作为指针是发出您不希望传递参数的信号的方式。将这些API转换为Delphi更为复杂。您需要使用指针实现版本,以允许调用方选择不提供参数。但是,为了方便调用方,提供使用 out
或 var
的重载版本可能会很有帮助。德尔福Windows
单元包含许多这样的例子。
至于WlanHostedNetworkQueryProperty
,我会这样声明:
const
// WLAN_HOSTED_NETWORK_OPCODE constants
wlan_hosted_network_opcode_connection_settings = 0;
wlan_hosted_network_opcode_security_settings = 1;
wlan_hosted_network_opcode_station_profile = 2;
wlan_hosted_network_opcode_enable = 3;
// WLAN_OPCODE_VALUE_TYPE constants
wlan_opcode_value_type_query_only = 0;
wlan_opcode_value_type_set_by_group_policy = 1;
wlan_opcode_value_type_set_by_user = 2;
wlan_opcode_value_type_invalid = 3;
function WlanHostedNetworkQueryProperty(
hClientHandle: THandle;
OpCode: Integer;
out DataSize: DWORD;
out Data: Pointer;
out WlanOpcodeValueType: Integer;
Reserved: Pointer
): DWORD; external 'Wlanapi.dll' delayed;
我使用了delayed
工具,因为这是一个Windows 7及更高版本的API。您可能希望程序在旧版本的Windows上运行,因此需要延迟加载。有关 Delphi 中延迟加载的更多信息,请参阅此答案,尤其是后续链接。
请注意,您链接到的 MSDN 主题中的文档不正确。pWlanOpcodeValueType
参数在 MSDN 主题中声明不正确。正确的定义,在wlanpi.h
中找到的定义是这样的:
__out PWLAN_OPCODE_VALUE_TYPE pWlanOpcodeValueType,