2013-01-18 22 views
10

Trình nghe thời gian dài, người gọi lần đầu tiên. Tôi biết đây là một câu hỏi hơi mơ hồ và không mong đợi quá nhiều. :-)Đang tải các đối tượng được chia sẻ Ada trong Perl với DynaLoader.pm

tôi có các tập tin Ada sau:

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; 

Và biên dịch chúng thành một đối tượng chia sẻ như này:

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

Việc biên dịch này tốt. nm cho thấy những biểu tượng sau:

$ 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 

Bây giờ tôi cố gắng để tải mà đối tượng được chia sẻ trong 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, $/; 
} 

Nhưng với thông báo sau bom này:

./libgreeter.so : undefined symbol: __gnat_eh_personality tại ./greeter.pl dòng 26.

Có ai có gợi ý nào không? Có cái gì tốt hơn/dễ hơn DynaLoader mà tôi nên sử dụng không ??

Tôi có một kho lưu trữ với tất cả các file liên quan ở đây:

Trả lời

9

Tôi không thể trợ giúp với bên Perl (bạn yêu cầu 5.14, Mac OS X có 5.12, Debian 6 có 5.10). Điều đó nói rằng, tôi có thể giúp xây dựng thư viện cho một liên kết chính và trực tiếp ...

Quy trình xây dựng GNAT đủ phức tạp để có hai công cụ hỗ trợ, gnatmakegprbuild. Có khả năng (viết vào tháng 9 năm 2015) rằng gnatmake sẽ mất khả năng xây dựng thư viện, do đó, gprbuild là tùy chọn tốt hơn.

Tôi nghĩ rằng bạn cần một dự án thư viện độc lập (có nghĩa là, một với các hoạt động khởi tạo và hoàn tất kiểm soát Ada, nếu bạn không khởi tạo thư viện Ada, bạn sẽ nhận được SEGV hoặc xấu khác hành vi). Bạn sẽ tìm thấy lowdown trên xây dựng một here.

Các greeter.gpr tôi đã viết là

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; 

Thuộc tính Library_Name điều khiển tên của thư viện; libgreeter.dylib trên Mac OS X, libgreeter.so trên Linux.

Thuộc tính Library_Kind có thể cách khác là "static", trong trường hợp đó tên sẽ là libgreeter.a. Tuy nhiên, thư viện độc lập phải có thể định vị lại.

Thuộc tính Library_Dir, mà bạn phải cung cấp (với cả hai ở trên) để tạo một thư viện, kiểm soát nơi thư viện được tạo; trong trường hợp này, trong lib/.

Bạn phải cung cấp thuộc tính Library_Interface để biến nó trở thành một thư viện độc lập và tạo các hoạt động khởi tạo và hoàn tất kiểm soát việc xây dựng Ada. Chúng được gọi là library_nameinit library_namefinal - tại đây, greeterinit, greeterfinal.

Nếu Library_Auto_Init"false" bạn phải gọi khởi tạo và các hoạt động hoàn thiện bản thân, nếu "true", họ đang quản lý cách tự động.

OK, xây dựng thư viện bằng cách

gprbuild -p -P greeter 

(-p nói "tạo ra bất kỳ thư mục đầu ra cần thiết", -P quy định cụ thể hồ sơ dự án).

tôi đã xây dựng greeter.c

#include <stdio.h> 

extern void greeter_hello(); 

int main() 
{ 
    greeter__hello(); 
    return 0; 
} 

sử dụng

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

và chạy (trên Linux) sử dụng

$ LD_LIBRARY_PATH=./lib ./greeter 
+0

Simon Wright ++, điều này đã cho tôi một số công cụ tốt để bắt đầu với. Tôi sẽ thử điều đó và nếu nó hoạt động, sẽ chấp nhận câu trả lời này. – tobyink

+0

Tôi chưa có tu để thử điều này, nhưng trong thời gian đó tôi đã chấp nhận câu trả lời vì có vẻ như nó hứa hẹn hơn cho cả hai. – tobyink

4

tôi sẽ làm tốt nhất tôi có thể với điều này, vì không có nhiều kiến ​​thức Perl.

Có vẻ như tôi là Dynaloader trong perl là một tiện ích cho phép bạn tải các thư viện có khả năng tải động (lib * .so trên các hệ thống Unix) vào một chương trình perl.

Để làm việc đó cho một chương trình Ada, có một số điều bạn sẽ cần phải tính đến.

  1. Bạn cần xây dựng chương trình Ada của mình làm thư viện động thích hợp. Có vẻ như bạn đã làm điều đó. Tuy nhiên, tôi không có chuyên gia về điều này, vì vậy có lẽ bạn đã bỏ lỡ một cái gì đó. Tôi rất muốn đề nghị tìm kiếm trên TFM về điều này.
  2. Bạn cần gọi mã Ada của mình đúng cách. Các chương trình Ada thường đòi hỏi một quá trình gọi là "xây dựng" được thực hiện trước khi bất kỳ mã thực tế nào có thể được chạy. Để thực hiện điều này, hầu hết các trình biên dịch Ada tạo ra một điểm vào đặc biệt cho chương trình, thay vì chỉ sử dụng một trình kết hợp với thường trình "chính" của bạn. Tôi nghĩ rằng Gnat là một cái gì đó giống như C_yourprogramname, nhưng không giữ tôi với điều đó. Ngay cả khi bạn đang thực hiện một thư viện của một số loại, việc xây dựng nên được chạy đầu tiên (execpt trong một số trường hợp đặc biệt, mà không áp dụng ở đây). Tuy nhiên, nếu bạn muốn một thói quen là một thói quen thư viện được gọi từ bên ngoài Ada, bạn thường không muốn có một "chính", do đó, có một số bước bổ sung.Làm thế nào để làm điều này với Gnat là described in their user guide, nhưng nói chung nó liên quan đến việc nói cho trình biên dịch không thực hiện một "chính", gọi adainit trước khi chạy bất kỳ thói quen Ada từ bên ngoài, và gọi adafinal khi bạn đã hoàn tất.
Các vấn đề liên quan