Delphi定义了外部WinAPI函数的类型

Rep*_*til 0 delphi winapi

我试图在delphi中调用CreateProcessWithLogonW函数

我的第一次尝试如下

function CreateProcessWithLogonW(
  lpUsername,
  lpDomain,
  lpPassword: LPCWSTR;
  dwLogonFlags: DWORD;
  lpApplicationName: LPCWSTR;
  lpCommandLine: LPWSTR;
  dwCreationFlags: DWORD;
  lpEnvironment: Pointer;
  lpCurrentDirectory: LPCWSTR;
  lpStartupInfo: TStartupInfo;
  lpProcessInfo: TProcessInformation
  ): BOOL;
    stdcall; external 'Advapi32.dll';
Run Code Online (Sandbox Code Playgroud)

一旦我在我的程序中调用它,我得到AV,我用谷歌搜索如何在Delphi中调用此函数,我发现lpStartupInfo并且lpProcessInfo必须定义如下

 var lpStartupInfo: TStartupInfo;
 var lpProcessInfo: TProcessInformation
Run Code Online (Sandbox Code Playgroud)

这些功能按预期工作.

我的问题:如果在调用上述外部WinAPI函数时函数参数必须是可变的,我现在怎么办?因为我没有在文档中找到有关此信息的信息.

Rem*_*eau 7

你的第一次尝试是接近但略有错误.正确的声明应该是这样的:

function CreateProcessWithLogonW(
  lpUsername,
  lpDomain,
  lpPassword: LPCWSTR;
  dwLogonFlags: DWORD;
  lpApplicationName: LPCWSTR;
  lpCommandLine: LPWSTR;
  dwCreationFlags: DWORD;
  lpEnvironment: Pointer;
  lpCurrentDirectory: LPCWSTR;
  lpStartupInfo: PStartupInfoW;
  lpProcessInfo: PProcessInformation
  ): BOOL;
    stdcall; external 'Advapi32.dll';
Run Code Online (Sandbox Code Playgroud)

请注意,最后两个参数是指针(LP表示Win32 API中的指针),因此您将声明非指针变量,然后使用@运算符将其内存地址传递给参数:

var
  StartupInfo: TStartupInfoW;
  ProcessInfo: TProcessInformation;
begin
  CreateProcessWithLogonW(..., @StartupInfo, @ProcessInfo);
end;
Run Code Online (Sandbox Code Playgroud)

但是,参数都是必需的,不能为零.在Delphi中,它是常规的1声明一个所需的指针参数作为非指针var参数,而不是:

function CreateProcessWithLogonW(
  lpUsername,
  lpDomain,
  lpPassword: LPCWSTR;
  dwLogonFlags: DWORD;
  lpApplicationName: LPCWSTR;
  lpCommandLine: LPWSTR;
  dwCreationFlags: DWORD;
  lpEnvironment: Pointer;
  lpCurrentDirectory: LPCWSTR;
  var lpStartupInfo: TStartupInfoW;
  var lpProcessInfo: TProcessInformation
  ): BOOL;
    stdcall; external 'Advapi32.dll';

...

var
  StartupInfo: TStartupInfoW;
  ProcessInfo: TProcessInformation;
begin
  CreateProcessWithLogonW(..., StartupInfo, ProcessInfo);
end;
Run Code Online (Sandbox Code Playgroud)

不过这只是一种便利.无论变量是通过指针还是通过引用传递,相同的内存地址仍然以任何方式传递给API.

1:Embarcadero有一个坏习惯,就是在Win32 API声明(而不是or )中声明可选的指针参数(可以是nil ).这使得用户在需要时更难实际传递nil指针(尽管仍然可以使用笨拙的类型转换来完成).var <type>P<type>^<type>