Free Pascal 链接 C/C++ 静态库

本文提供的方法仅在 Windows 中测试通过,未在 Linux 中进行过测试,但理论上也能使用。

Free Pascal 中可以用非常简单的代码链接到动态库:

pascalfunction MyAdd(x, y: Integer): Integer; external 'mylib.dll' name 'MyAdd';

另外也可以链接到静态库,这样分发程序的时候就不用带上一堆 DLL 文件了。

首先将 C 代码编译为静态库,然后在 Lazarus > 项目选项 > 编译器选项 > 路径 > 库 (-Fl) 中输入静态库存放的路径。此处以 C 编写的静态库导出 MyAdd() 函数为例,演示如何在 Free Pascal 中调用它。

C 代码如下:

cextern int MyAdd(int x, int y)
{
    return x + y;
}
mylib.c

使用 gcc 编译后生成的静态库文件名为 libmylib.a(也可以使用 MSVC 编译,但编译后的静态库需要额外处理,后文会提到)。

Pascal 链接和调用静态库的代码如下:

pascalprogram main;

{$LINKLIB 'mylib'}

function MyAdd(x, y: Integer): Integer; cdecl; external;  

begin
  WriteLn(Format('123 + 456 = %d', [MyAdd(123, 456)]));
end.  
main.pas

需要注意以下问题:

  1. 静态库的扩展名必须是 .a 。如果是其他扩展名,fpc 会将其视作 DLL 动态链接库,导致链接失败;
  2. 若静态库文件名为 libxyz.a,链接时可写作 {$LINKLIB xyz},能省略 lib 前缀和 .a 扩展名;
  3. fpc 可支持 gcc 编译器生成的静态库;
  4. 如果是 MSVC 编译的静态库,需要使用 ranlib 命令(包含于 WinLibs)转格式;
  5. fpc 不支持 clang 编译器生成的静态库,似乎是 COFF 格式有问题。

假设 MSVC 编译的静态库文件名为 mylib.lib,处理命令如下:

powershellranlib mylib.lib
mv mylib.lib libmylib.a

fpc 所使用的链接工具和 gcc 的一样,是由 GNU Binutils 提供的 ld,而 clang 使用的链接工具是 LLVM 提供的 lld。不过 gcc 是可以链接 clang 编译的静态库的,也许可以手动使用 ar 命令将 clang 编译生成的 .o 文件封装成 .a 静态库。感兴趣的读者可以“亲自编译、亲自测试”一下。