2013-01-18 12 views
10

長時間リスナー、初回呼び出し元。私はこれがやや不明瞭な質問であると認識しており、あまり期待していません。 :-)PerlでDynaLoader.pmを使用してAda共有オブジェクトをロードする

私は、次のエイダファイルがあります。

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; 

などの共有オブジェクトにコンパイルしをthis:

gnatmake -z -fPIC greeter.adb 
gcc -shared -o libgreeter.so greeter.o 

これは正常にコンパイルされます。 nmは、次の記号を示しています。次のメッセージと一緒に

#!/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, $/; 
} 

しかし、この爆弾:

$ 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 

は今、私はPerlでその共有オブジェクトをロードしようと

./libgreeter.so :未定義シンボル:__gnat_eh_personality at ./greeter.pl 26行目。

誰かヒントはありますか? DynaLoaderよりも優れた/簡単なものがありますか?

私はここに関連するすべてのファイルとリポジトリ持っている:私はあまりいないPerlの知識が与えられ、これで私ができる最善を尽くします

答えて

9

私はPerl側(5.14が必要、Mac OS Xは5.12、Debian 6は5.10)を手伝ってはいけません。つまり、私はCメインと直接リンクのためのライブラリを構築することができます...

GNATビルドプロセスは、それをサポートする2つのツール、つまりgnatmakegprbuildがあります。 gnatmakeはライブラリを構築する能力を失うため、gprbuildがより良い選択肢です(2015年9月の時点)。

スタンドアロンのライブラリプロジェクトが必要です(つまり、Adaエラボレーションを制御する初期化とファイナライズ操作を行うもの、Adaライブラリを初期化しないと、SEGVまたはその他の悪い行動)。 hereを建てることについての裏庭があります。

私が書いたgreeter.gpr

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; 

Library_Name属性は、ライブラリの名前を制御しています。 Mac OS Xではlibgreeter.dylib、Linuxではlibgreeter.soです。

Library_Kind属性は、"static"とすることもできます。その場合、名前はlibgreeter.aになります。ただし、スタンドアロンライブラリは、再配置可能でなければなりません

ライブラリを作成するために(上記2つの)Library_Dir属性を指定する必要があり、ライブラリの作成場所を制御します。この場合、lib/にあります。

アトリビュートをスタンドアロンライブラリにして、Adaエラボレーションを制御する初期化とファイナライズ操作を生成するには、Library_Interface属性を指定する必要があります。 library_nameinit library_namefinal - ここではgreeterinitgreeterfinalと呼ばれています。

Library_Auto_Init"false"の場合は、"true"の場合は、自動的に初期化処理とファイナライズ処理を呼び出す必要があります。

gprbuild -p -P greeter 

-p "は、任意の必要な出力ディレクトリを作成する" と言い、-Pは、プロジェクトファイルを指定する)ことにより、ライブラリを構築

OK、。私は

$ LD_LIBRARY_PATH=./lib ./greeter 
+0

サイモン・ライト++を使用して

$ gcc greeter.c -o greeter -L lib -l greeter 

と(Linuxの場合)の実行を使用してgreeter.c

#include <stdio.h> extern void greeter_hello(); int main() { greeter__hello(); return 0; } 

を建て

、これは私を始めるためにいくつかの良いものを与えています。私はそれを試してみて、それがうまくいくなら、この答えを受け入れます。 – tobyink

+0

私はまだこれを試してみるのは難しいですが、その間に私は答えを受け入れました。 – tobyink

4

を。

perlのDynaloaderは、動的にロード可能なライブラリ(Unixシステム上のlib * .so)をperlプログラムに読み込むユーティリティです。

Adaプログラムで動作するには、考慮する必要があります。

  1. Adaプログラムを適切な動的ライブラリとして構築する必要があります。あなたがそうしたように見えます。しかし、私はこれについて専門家ではないので、おそらくあなたは何かを逃した。私は非常にこの上TFMを見てお勧めします。
  2. あなたのAdaコードを正しく呼び出す必要があります。 Adaプログラムでは、一般に、実際のコードを実行する前に「精緻化」というプロセスを実行する必要があります。これを達成するために、ほとんどのAdaコンパイラは、あなたの "メイン"ルーチンに関連するものを使用するのではなく、プログラムの特別なエントリポイントを作成します。私はGnat'sがC_yourprogramnameのようなものだと思っていますが、私にそれを抱かないでください。何らかのライブラリを実装していても、最初に実行する必要があります(ここでは適用されない特別な状況ではexecpt)。しかし、ルーチンをAdaの外部から呼び出されるライブラリルーチンにしたいのであれば、一般に "main"は必要ないので、いくつかの追加ステップがあります。Gnatでこれを行う方法はdescribed in their user guideですが、一般的には、外部からAdaルーチンを実行する前にadainitを呼び出し、すべて完了したらadafinalを呼び出すように、コンパイラーに "メイン"を行わないように指示します。
関連する問題