是否可以使用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);
答案 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从原始代码派生的。