我可以在Delphi中使用C头吗?

时间:2011-01-06 11:48:53

标签: c delphi header c++builder

是否可以使用Rad Studio XE C ++编译器编译C头并将它们与Delphi代码链接?

因此无需将头文件转换为pascal?

问题的原因是......

C - 标题定义:

DLLEXPORT int url_engine_version(char *version, size_t length);

尝试Delphi定义

function url_engine_version(version: PByte; var length: cardinal): integer;
  cdecl; external 'corplib.dll';

主应用程序尝试使用以下方法调用它:

engVer: Pointer;
engLen: cardinal;

engLen := 64;
GetMem(engVer,engLen);
url_engine_version(engVer,engLen);

但Delphi AV试图调用例行程序时。

使用C#定义 - 如果我传递一个预定义为长度为64的StringBuilder

,Chick就可以工作
[DllImport("corplib.dll", CharSet = CharSet.Ansi,
           CallingConvention = CallingConvention.Cdecl)]
public static extern int url_engine_version(StringBuilder version, [Out] int length);

3 个答案:

答案 0 :(得分:3)

您实际问题的答案是:不。抱歉。

但是,我认为在这种情况下问题很简单......

你在这里复制的C标题是错误的还是C#声明,或者你很幸运没有让C#代码崩溃并且像Delphi代码那样严重烧坏。

我认为问题是C Header将 length 参数声明为SIZE_T, NOT 指向SIZE_T的指针。即它是输入参数,而不是输出或输入/输出参数。

您可能使用 length 来指定为在 version 中传递的指针分配的缓冲区大小。我进一步假设函数返回用于放置在 version 缓冲区中的数据的实际字节数。

我相信Delphi版本会崩溃,因为通过将 length 指定为 var ,您将通过引用传递 length ,即函数接收不是“64”而是指向值“64”的指针,但是它使用的是指针值,而不是64值。

C#代码可能会躲避子弹(如果C标头本身正确,也可能不正确)将参数声明为 out 。这可能会转化为某些内容,如果不正确,至少在运行时不会出现“有害的错误”。

我认为只需从长度参数声明中删除“var”就可以解决您的问题:

function url_engine_version(aVersion: PByte; aLength: cardinal): integer; cdecl; external 'corplib.dll';

答案 1 :(得分:1)

转换的主要问题是类型系统的差异。一个好的delphi头文件不能从c。

派生

例如,c不区分指向一个元素的指针和指向数组的指针。它不区分bools和int。 char*可以表示零终止字符串,指向字节的指针,指向单个字符的指针,通过引用传递的字符,...

在你的例子中,delphi代码通过引用传递最后一个参数(即作为指向UInt32的指针),而c代码则没有。但我不明白为什么C#代码有效。

答案 2 :(得分:0)

Project JEDI为Delphi做了很多C头转换。他们在website上有一套优秀的资源,教程等。

他们还有一个可以自动执行此操作的工具,该工具实际上是由Bob Swart从原始代码派生的。