Sunday, March 11, 2007

Calling a C++ library from FreePascal

It took me a few hours to figure this out - well, not totally figured out yet.

I wanted to call a library from FreePascal. It's a static library (.a file) that's written in C++ and exposes some API functions. Here's how I started:

function myfunc(): int; cdecl; external 'mylib';

FPC fails to find the function. I then realize that I need to use the C++ mangled function name. Complination and linking worked but the program seg-faults upon running.

I then give up the idea of directly accessing it. Instead, I write a wrapper shared lib (.so file) in C++, and expose a C API with extern C" {}. I also wrote a tester program in C to test the wrapper with. Then I get some "undefined reference to std::basic_string..." errors. I tried this but it still didn't work:

{$LINKLIB /usr/lib/gcc/i486-linux-gnu/4..2/libstdc++.a}

I then tried adding libstdc++.a to the .so wrapper lib. It worked! Then my linux box crashed. To make things worse, there was an on-going aptitude update that actually removed X window from my kubuntu. So when I booted up, I only got a console. After I got my X window back, my code stopped working again.

Eventually, I figured out that the original /usr/lib/gcc-lib/i486-linux-gnu/3.3.6/libstdc++.a libstdc++.a was removed in the aptitude upgrade. And the file in /usr/lib/gcc/i486-linux-gnu/4.0.2 didn't work. So I tried to get the older version of libstdc++.a with adept, and it finally worked.

After the C test program work, it didn't take long to make FPC code work with the wrapper lib. All I needed to do was:

{$LINKLIB libmylib.a}
function myfunc(): int; cdecl; external 'mywrapper.so';

No comments: