【问题标题】:consuming C dlls with Delphi使用 Delphi 使用 C dll
【发布时间】:2012-08-03 00:24:53
【问题描述】:

我有一个带有这个签名的 Dll 函数:

UInt32 Authenticate(uint8 *Key);

我在 Delphi 上这样做:

function Authenticate(Key:string) : UInt32; external 'mylib.dll' name 'Authenticate';

但总是,函数返回 10(错误代码)并且应用程序停止:\

有办法做到这一点吗?

更新: 谢谢大家!你是最棒的!

【问题讨论】:

  • 当然 uint8 不等同于字符串......你应该将什么作为键传递给函数,只是一个指向字节的指针?
  • @jachguate uint8* 等价于 PAnsiChar,在这种情况下
  • @David,在这种情况下,等效项是模棱两可的 XD。恕我直言,uint8 仅相当于一个 PByte。通过 uint8 指针期望 PAnsiChar 的函数不是等价问题,而是 c 端的偏好问题。我不太同意的一个。

标签: c delphi dll freepascal lazarus


【解决方案1】:

您的代码存在一些问题。

1) uint8 在 Delphi 中等同于 Byte,而不是 String

2) C 代码使用编译器的默认调用约定,通常为__cdecl。另一方面,Delphi 的默认调用约定是register。它们彼此不兼容。如果调用约定不匹配,则在运行时函数调用期间将无法正确管理堆栈和 CPU 寄存器。

C 代码的字面翻译应该是这样的:

function Authenticate(Key: PByte) : UInt32; cdecl; external 'mylib.dll';

但是,假设该函数实际上需要一个以空字符结尾的字符串,则改为执行以下操作:

// the function is expecting a pointer to 8-bit data,
// so DO NOT use `PChar`, which is 16-bit in Delphi 2009+...
function Authenticate(Key: PAnsiChar) : UInt32; cdecl; external 'mylib.dll';

我会坚持第一个声明,因为它与原始 C 代码匹配。即使该函数需要一个以空字符结尾的字符串作为输入,您仍然可以使用PByte 通过类型转换将其传递:

var
  S: AnsiString;
begin
  Authenticate(PByte(PAnsiChar(S)));
end;

或者,如果函数允许空字符串输入 NULL:

var
  S: AnsiString;
begin
  Authenticate(PByte(Pointer(S)));
end;

【讨论】:

  • 绝对是一个好的开始。值得注意的是,对于低于 Delphi 2008 的版本,Delphi 使用 8 位 ASCII,在这种情况下,将首选 PChar。这是关于 Delphi 字符串处理和与 Windows 兼容性的极好链接:delphi.about.com/od/beginners/l/aa071800a.htm
  • PAnsiChar 仍然比 PChar 更受欢迎,即使在 2009 年之前的 Delphi 版本中也是如此。它使代码更明确地表明它需要 8 位字符数据,如果项目是稍后升级到 2009+ 版本的 Delphi。
【解决方案2】:

我不会在伟大的 Remy 的回答中添加任何内容,但我想列出可以帮助将 C DLL 头文件转换为 Pascal 的工具(无特殊顺序):

请注意,这些转换器只能转换 60-80% 的代码,因此需要手动操作。

我可以给出的最大的节省时间的提示是尝试找到适用于您的 DLL 的 Visual Basic 头文件翻译,并在http://www.marcocantu.com/tools/vb2delphi.htm 使用 Marco Cantu 的 VB 转换器。这可能会为您提供几乎 100% 的自动转换(当然,如果您只是转换 DLL 标头)。还有一个商业 VBTO 转换器,但试用演示足以将 VB DLL 头文件转换为 Pascal。在这里下载:http://www.vbto.net

从 C--/C++ 转换的其他技巧:

有点偏离主题,但我认为这可能对某人有用...

【讨论】:

    【解决方案3】:

    对于初学者,将“string”更改为“pchar”。

    除此之外可能还有其他问题。

    【讨论】:

    • 如果使用 Delphi 2009+,请使用 PAnsiChar
    • PByteArray 是更精确的变量类型。
    • 这不是答案。还有更多的问题,PChar 无论如何都是错误的,因为PChar 不是pointer to 8-byte unsigned integer 的替代品(当然string 也不是)。充其量应该是对原始问题的评论;这当然不是答案。
    • @Ken - uint8 是 8 位,而不是字节,即字节。见msdn.microsoft.com/en-us/library/cc230388%28v=prot.10%29.aspx
    • @Gerry:当然可以。就我而言,错字了,我写的东西读得不够好。感谢您的更正 - 不需要链接,但我感谢提供它的努力。再次感谢。 :-)
    猜你喜欢
    • 2013-03-23
    • 1970-01-01
    • 2016-11-07
    • 1970-01-01
    • 2011-04-03
    • 1970-01-01
    • 2011-01-08
    • 2011-04-07
    • 1970-01-01
    相关资源
    最近更新 更多