Loading Ada shared objects in Perl with DynaLoader.pm
ada, linker, perl, shared-libraries
Solution
I can't help with the Perl side (you require 5.14, Mac OS X has 5.12, Debian 6 has 5.10). That said, I can help with building the library for a C main and direct linking ...
The GNAT build process is sufficiently complicated that there are two tools to support it, `gnatmake` and `gprbuild`. It’s likely (writing at September 2015) that `gnatmake` will lose the ability to build libraries, so `gprbuild` is the better option.
I think you need a stand-alone library project (that is, one with the initialization and finalization operations that control Ada elaboration; if you don't initialize the Ada library, you'll get SEGVs or other bad behaviours). You'll find the lowdown on building one here.
The `greeter.gpr` I wrote is
project Greeter is
for Library_Name use "greeter";
for Library_Kind use "relocatable";
for Library_Dir use "lib";
for Library_Interface use ("greeter");
for Library_Auto_Init use "true"; -- the default, I think
for Object_Dir use ".build"; -- to keep temp objects out of the way
end Greeter;
The `Library_Name` attribute controls the name of the library; `libgreeter.dylib` on Mac OS X, `libgreeter.so` on Linux.
The `Library_Kind` attribute could alternatively be `"static"`, in which case the name would be `libgreeter.a`. However, stand-alone libraries must be relocatable.
The `Library_Dir` attribute, which you have to supply (with the two above) to make a library at all, controls where the library is created; in this case, in `lib/`.
You have to supply the `Library_Interface` attribute to make it a stand-alone library and generate the initialization and finalization operations that control Ada elaboration. They're called library_name`init` and library_name`final` - here, `greeterinit`, `greeterfinal`.
If `Library_Auto_Init` is `"false"` you have to call the initialization and finalization operations yourself, if `"true"`, they're managed automagically.
OK, build the library by
gprbuild -p -P greeter
(`-p` says "create any needed output directories", `-P` specifies the project file).
I built `greeter.c`
#include <stdio.h>
extern void greeter_hello();
int main()
{
greeter__hello();
return 0;
}
using
$ gcc greeter.c -o greeter -L lib -l greeter
and run (on Linux) using
$ LD_LIBRARY_PATH=./lib ./greeter
Problem
Long time listener, first time caller. I'm aware this is a somewhat obscure question, and don't expect too much. :-) I have the following Ada files: greeter.ads ``` package Greeter is procedure Hello; end Greeter; ``` greeter.adb ``` with Ada.Text_IO; use Ada.Text_IO; package body Greeter is procedure Hello is begin Put_Line ("Hello, world!"); end Hello; end Greeter; ``` And compile them into a shared object like this: ``` gnatmake -z -fPIC greeter.adb gcc -shared -o libgreeter.so greeter.o ``` This compiles fine. `nm` shows the following symbols: ``` $ nm -D libgreeter.so w _Jv_RegisterClasses 0000000000201028 A __bss_start w __cxa_finalize w __gmon_start__ U __gnat_eh_personality 0000000000201028 A _edata 0000000000201038 A _end 00000000000006a8 T _fini 0000000000000520 T _init U ada__text_io__put_line__2 0000000000201018 D greeter_E 000000000000063c T greeter__hello ``` Now I try to load that shared object in Perl: ``` #!/usr/bin/env perl use 5.014; use strict; use warnings; #BEGIN { $ENV{PERL_DL_DEBUG} = 1 }; package Greeter { use constant ADADIR => '/usr/lib/gcc/x86_64-linux-gnu/4.4/rts-native/adalib/'; use constant OURDIR => do { (my $f = __FILE__) =~ s{[^/]+$}//; $f || "." }; require DynaLoader; our @ISA = 'DynaLoader'; my $runtime = DynaLoader::dl_load_file( ADADIR.'/libgnat.so', ) or die DynaLoader::dl_error(); my $gep = DynaLoader::dl_find_symbol( $runtime, '__gnat_eh_personality', ) or die DynaLoader::dl_error(); my $libref = DynaLoader::dl_load_file( OURDIR.'/libgreeter.so', 0x01, ) or die DynaLoader::dl_error(); my $func = DynaLoader::dl_find_symbol( $libref, 'greeter__hello', ) or die DynaLoader::dl_error(); print $func, $/; } ``` But this bombs out with the following message: ./libgreeter.so: undefined symbol: __gnat_eh_personality at ./greeter.pl line 26. Does anybody have any hints? Is there something better/easier than DynaLoader that I should be using?? I have a repository with all the relevant files here: - https://bitbucket.org/tobyink/ada-perl-mashup