如何在Delphi中连接(导入)WinApi函数

Gu.*_*u. 2 delphi winapi delphi-xe4

德尔福Xe4.例如,有两个函数(Unicode):

CryptAcquireContext,CryptGetProvParam.

我在MSDN上阅读说明:

1)http://msdn.microsoft.com/en-us/library/windows/desktop/aa379886(v=vs.85 ) .aspx

BOOL WINAPI CryptAcquireContext(
  _Out_  HCRYPTPROV *phProv,
  _In_   LPCTSTR pszContainer,
  _In_   LPCTSTR pszProvider,
  _In_   DWORD dwProvType,
  _In_   DWORD dwFlags);
Run Code Online (Sandbox Code Playgroud)

2)http://msdn.microsoft.com/en-us/library/windows/desktop/aa379929(v=vs.85 ) .aspx

BOOL WINAPI CryptEnumProviders(
  _In_     DWORD dwIndex,
  _In_     DWORD *pdwReserved,
  _In_     DWORD dwFlags,
  _Out_    DWORD *pdwProvType,
  _Out_    LPTSTR pszProvName,
  _Inout_  DWORD *pcbProvName);
Run Code Online (Sandbox Code Playgroud)

如果我理解正确,那么翻译成Delphi应该是这样的:

    {S} Function CryptAcquireContext(Out hpProv:PNativeUInt;Const Container:PWideChar;
Const Provider:PWideChar;Const ProvType:DWord;Const Flags:DWord):Bool; StdCall; External Advapi32dll Name 'CryptAcquireContextW';

    {S} Function CryptEnumProviders(Const Index:DWord;Const Reserved:PDWord;Const Flags:DWord;
Out ProvType:PDWord;Out pszProvName:DWord;Var pcbProvName:DWord):Bool; StdCall; External Advapi32dll Name 'CryptEnumProvidersW';
Run Code Online (Sandbox Code Playgroud)

主要对返回参数参数感兴趣,标有"OUT"和"VAR"(Out,InOut).因此,我不会使用interente中的各种示例.例如电话:

Procedure Test;
var hProv:NativeUInt;provName: array[0..200] of char;dwProvType: DWORD;
begin
...
if not CryptAcquireContext(@hProv, nil, provName, dwProvType,CRYPT_VERIFYCONTEXT) then RaiseLastOSError;
...
while CryptEnumProviders(i, nil, 0,@dwProvType, nil, @cbName)) do
begin
..
end;
Run Code Online (Sandbox Code Playgroud)

给出编译错误:"E2033实际和正式var参数的类型必须相同" - 指的是@hProv和@dwProvType.如果您想在VAR上替换OUT并在PDword(dwProvType)上替换文本@dwProvType,则会出现错误:"E2197常量对象不能作为var参数传递".

如果我没有指定输入和输出参数(像这样 - http://www.bvbcode.com/code/oyma7f3h-1618784,字符串№692),一切都编译,运行和工作正常(Const - 无效):

{S} Function CryptAcquireContext(hpProv:PNativeUInt;Container:PWideChar;Provider:PWideChar;ProvType:DWord;Flags:DWord):Bool; StdCall; External Advapi32dll Name 'CryptAcquireContextW';

{S} Function CryptEnumProviders(Index:DWord;Reserved:PDWord;Flags:DWord;ProvType:PDWord;pszProvName:PWideChar;pcbProvName:PDWord):Bool; StdCall; External Advapi32dll Name 'CryptEnumProvidersW';
Run Code Online (Sandbox Code Playgroud)

在过去,我被建议采用JEDI API函数的值.我下载了最新版本的(http://sourceforge.net/projects/jedi-apilib/),我看到(单位JwaWinCrypt):

function CryptAcquireContext(var phProv: HCRYPTPROV; pszContainer: LPCTSTR;
  pszProvider: LPCTSTR; dwProvType: DWORD; dwFlags: DWORD): BOOL; stdcall;

function CryptEnumProviders(dwIndex: DWORD; pdwReserved: LPDWORD; dwFlags: DWORD;
  var pdwProvType: DWORD; pszProvName: LPTSTR; var pcbProvName: DWORD): BOOL; stdcall;
Run Code Online (Sandbox Code Playgroud)

相反,调用"OUT"和"INOUT"的值写"VAR".但是这些我的例子都不行.和DWORD类型的pdwProvType和pcbProvName,虽然描述是DWORD*= PDWORD?

问题:

1)如何正确行事.MSDN OUT = Delphi OUT还是VAR?IN_OUT = Delphi VAR?或者他们没有说明?

2)我需要写Const吗?IN = Delphi Const?

3)带指针的类型.DWORD = Delphi Dword.好.DWORD*= Delphi PDWROD(或所​​有标记的*= Delphi指针类型)?

ps对不起英语不好意思.

Dav*_*nan 6

声明HCRYPTPROV的类型:

type
  HCRYPTPROV = NativeUInt;
Run Code Online (Sandbox Code Playgroud)

然后声明函数:

function CryptAcquireContext(
    out hpProv: HCRYPTPROV; 
    Container: PWideChar;
    Provider: PWideChar;
    ProvType: DWORD;
    Flags: DWORD
):BOOL; stdcall; external Advapi32dll name 'CryptAcquireContextW';

function CryptEnumProviders(
    Index: DWORD;
    Reserved: PDWORD;
    Flags: DWORD;
    out ProvType: DWORD;
    pszProvName: PWideChar;
    var pcbProvName: DWORD
):BOOL; stdcall; external Advapi32dll name 'CryptEnumProvidersW';
Run Code Online (Sandbox Code Playgroud)

请注意,var和out参数作为指向实际参数的指针传递.所以在你的代码中你会有太多的间接性.

在我的翻译中,我采用了以下政策:

  • 值参数不使用const.外部声明似乎没什么好处.
  • 指针参数由var或out优先传递.对于像这样的简单类型,out和var具有相同的实现,使用其中一个的唯一原因是记录参数语义.
  • 可选的指针参数被声明为指针,以允许调用者传递nil.