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

标签 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);

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);

如果我理解正确的话,翻译成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';

主要对返回参数感兴趣,标记为“OUT”和“VAR”(OutInOut)。 因此,我不会使用 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;

给出编译错误:“E2033 实际和形式 var 参数的类型必须相同”——指@hProv 和@dwProvType。如果您想替换 VAR 上的 OUT 和 PDword(dwProvType) 上的文本 @dwProvType,则会出现错误:“E2197 常量对象无法作为 var 参数传递”。

如果我不指定输入和输出参数(例如 - http://www.bvbcode.com/code/oyma7f3h-1618784 ,字符串 №692),则一切都会编译、运行并正常工作(常量 - 无效果):

{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';

以前的题目建议我取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;

相反,将“OUT”和“INOUT”的值写入“VAR”。但我的这些例子并不能很好地工作。而DWORD类型的pdwProvType和pcbProvName,虽然描述是DWORD * = PDWORD?

问题:

1)如何正确地做。 MSDN OUT = Delphi OUT 还是 VAR? IN_OUT = 德尔福VAR?或者他们没有指定?

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

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

附:抱歉英语不好。

最佳答案

声明 HCRYPTPROV 的类型:

type
  HCRYPTPROV = NativeUInt;

然后声明函数:

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';

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

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

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

关于delphi - 如何在Delphi中连接(导入)WinApi函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17673201/

相关文章:

winapi - 以编程方式选择 MFC 单选按钮

delphi - 如何从 SQL Express 2012 获取数据更改通知?

delphi - 如何在泛型类中声明枚举类型的集合类型

c++ - Windows Media 基金会 : How to set an encoder property?

ios - 在 StringGrid 中输入值时是否可以设置键盘类型?

delphi - 如何从项目中查找并删除未使用的 Delphi 包

delphi - 如何分配多行字符串值而不引用每一行?

string - 如何从字符串中删除重复的空格

delphi - 将 TFDMemTable 数据附加到一个 XML 文件中

c++ - 传递给 CreateProcess 的参数未按我预期的那样进行解析