Delphi定义外部WinAPI函数的类型

Delphi定义外部WinAPI函数的类型,delphi,winapi,Delphi,Winapi,我试图调用delphi中的函数 我的第一次尝试如下 function CreateProcessWithLogonW( lpUsername, lpDomain, lpPassword: LPCWSTR; dwLogonFlags: DWORD; lpApplicationName: LPCWSTR; lpCommandLine: LPWSTR; dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrent

我试图调用delphi中的函数

我的第一次尝试如下

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';
一旦我在程序中调用它,我就得到了AV,我知道如何在Delphi中调用这个函数,我发现lpStartupInfo和lpProcessInfo必须定义如下

 var lpStartupInfo: TStartupInfo;
 var lpProcessInfo: TProcessInformation
这些函数按预期工作


我的问题是:如果在调用上述外部WinAPI函数时函数参数必须是可变的,我现在该怎么做。因为我在文件里找不到这个信息

您的第一次尝试很接近,但有点错误。正确的声明应如下所示:

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';
请注意,最后两个参数是Win32 API中的指针LP means pointer,因此您可以声明非指针变量,然后使用@运算符将其内存地址传递给参数:

var
  StartupInfo: TStartupInfoW;
  ProcessInfo: TProcessInformation;
begin
  CreateProcessWithLogonW(..., @StartupInfo, @ProcessInfo);
end;
但是,参数都是必需的,不能为零。在Delphi中,通常1将所需的指针参数声明为非指针变量参数:

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;
不过,这只是一种方便。无论变量是通过指针还是通过引用传递,相同的内存地址仍然以任何方式传递给API


1:Embarcadero有一个坏习惯,就是在Win32 API声明中将可选指针参数(可以为nil)声明为var,而不是p或^。这使得用户很难在想要传递nil指针时,使用一种笨拙的类型转换。如果函数参数必须是可变的,我现在怎么做MSDN文档很清楚。结构参数作为结构的地址传递。你读过C吗?@B我的意思是var lpProcessInfo:TProcessInformation或lpProcessInfo:TProcessInformation我如何知道正确的类型,也许我不知道如何表达我的问题或对其建模,但是,因为我的母语不是英语,这些参数必须通过引用,这包括指针。传递值无效。var lpProcessInfo:TProcessInformation-var参数和out参数始终是通过引用传递的。常量参数可以是按值计算的小参数,如整数,也可以是按引用计算的长参数。Delphi必须复制既不是const也不是var/out的参数,以便函数可以在其中进行局部更改。所以最好避免它们:-好吧,若文档列出的结构化参数是可选的-将其保留为指针,否则转换为byref。另一种可能是添加重载版本。@FreeConsulting:重载可能会变得丑陋,这取决于涉及的参数数量以及其中有多少是可选的或必需的。在这种情况下,我更喜欢转换为API中定义的实际类型、维护API预期语义的指针,并简化跨语言翻译。非常感谢,我想让你知道我是多么重视你的支持。