如何正确地将C与Delphi静态链接?

use*_*124 4 delphi delphi-xe8

如何正确地将C与Delphi静态链接?德尔福吐出一个错误说:

[dcc32错误] Project1.dpr(15):E2065不满意的前向或外部声明:'测试'

C编译器是带有COFF目标文件的Visual C++.

德尔福:

program Project1;

{$L C:\Source.obj}

function Test(): Integer; cdecl; external;

begin
  WriteLn(Test);
end.
Run Code Online (Sandbox Code Playgroud)

C:

extern "C" int __cdecl Test()
{
    return 12;
}

int main()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 6

它取决于您使用的任何C编译器使用的名称修饰.例如,32位bcc32编译器将装饰Test_Test.所以链接到它的Delphi代码应该是:

function Test(): Integer; cdecl; external name '_Test';
Run Code Online (Sandbox Code Playgroud)

但是编译器之间的装饰确实有所不同,并且您没有说明您使用的是哪种编译器.如果上面的代码没有帮助,那么您应该使用C编译器的工具来转储obj文件并检查其中的函数名称.

另一个问题是您实际上使用的是C++编译器而不是C编译器.从你的使用中可以看出这一点

extern "C" 
Run Code Online (Sandbox Code Playgroud)

这是无效的C.你应该删除它并切换到C编译器.将扩展名从.cpp更改为.c通常足以说服编译器将代码视为C.

如果您开始调用C标准库中的函数,例如malloc和朋友,那么您将需要将该System.Win.Crtl单元添加到Delphi代码的uses子句中.

另请注意,您不需要(实际上可能不应该)main在C代码中实现函数.如果要将C函数编译为单独的C程序,则将函数放在单独的源文件中,而不是包含main函数的源文件.这样您就可以将源文件编译为对象.您可以将它们链接到C程序或Delphi代码中.但是你不需要main在Delphi程序中携带一个你不打电话的函数.

在C中,无参数的正确签名main

int main(void)
Run Code Online (Sandbox Code Playgroud)

同样,你的其他C函数应该有这个签名:

int __cdecl Test(void)
Run Code Online (Sandbox Code Playgroud)

当然,这__cdecl是默认的,所以我们完全可以省略它:

int Test(void)
Run Code Online (Sandbox Code Playgroud)

让我们把它们放在一起:

C

int Test(void)
{
    return 12;
}
Run Code Online (Sandbox Code Playgroud)

重要的是,您使用C编译器进行编译,而不是作为C++编译.如果编译是,正如您现在在编辑MSVC中所述,命令行将是:

cl /c source.c

德尔福

{$APPTYPE CONSOLE}

{$L Source.obj}

function Test: Integer; cdecl; external name '_Test';

begin
  WriteLn(Test);
end.
Run Code Online (Sandbox Code Playgroud)

产量

12