载入阿达共享对象在Perl与DynaLoader.pm(Loading Ada shared obj

2019-08-07 08:04发布

很长一段时间听众,第一次调用者。 我知道这是一个有点模糊的问题,也不要抱太大的期望。 :-)

我有以下阿达文件:

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;

并编辑出版这样的共享对象:

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

编译没有问题。 nm显示了以下符号:

$ 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:

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

但这种炸弹不与下面的消息:

./libgreeter.so:未定义的符号:__gnat_eh_personality在./greeter.pl线26。

没有任何人有任何提示? 是否有更好的东西/比我应该使用动态加载更容易?

我有一个在这里的所有相关文件的存储库:

  • https://bitbucket.org/tobyink/ada-perl-mashup

Answer 1:

我不能用Perl的侧面帮助(你需要5.14,Mac OS X中有5.12,Debian的6拥有5.10)。 这就是说,我可以用构建库一个C主要和直接链接帮助...

蚋构建过程充分复杂,有支持的话,这两个工具gnatmakegprbuild 。 这是可能的(在2015年9月写),其gnatmake将失去建库的能力,因此gprbuild是更好的选择。

我认为你需要一个 (即一个与初始化和对照ADA阐述定稿操作;如果不初始化的Ada库,你会得到SEGVs或其他不良行为)。 你会发现一个建设的内幕这里 。

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属性控制库的名称; libgreeter.dylib在Mac OS X, libgreeter.so在Linux上。

Library_Kind属性可以替代地是"static" ,在这种情况下,名称将是libgreeter.a 。 然而, 独立的库必须重定位

Library_Dir属性,您必须提供(与上面两个),以使库所有,在其中创建库的控制; 在这种情况下,在lib/

你必须提供Library_Interface属性使它成为一个独立的库,产生的初始化和对照ADA阐述定稿操作。 他们被称为 initfinal -在这里, greeterinitgreeterfinal

如果Library_Auto_Init"false" ,你必须自己调用初始化和结束操作,如果"true" ,他们自动地管理。

OK,通过建库

gprbuild -p -P greeter

-p为“创建任何需要的输出目录”, -P指定项目文件)。

我内置greeter.c

#include <stdio.h>

extern void greeter_hello();

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

运用

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

并使用(在Linux上)运行

$ LD_LIBRARY_PATH=./lib ./greeter


Answer 2:

我会做这个尽我所能,给没有太多的Perl的知识。

在我看来像动态加载在Perl是一种实用工具,让您加载动态地加载库(LIB *。所以对Unix系统)到Perl程序。

为实现这一目标对于Ada的程序工作,有几件事情你需要考虑到。

  1. 你需要建立你的Ada程序作为一个适当的动态库。 它看起来像你这样做。 不过,我没有这方面的专家,所以也许你错过了什么。 我强烈建议在此找过TFM。
  2. 您需要正确地调用您的Ada代码。 阿达程序一般需要任何实际的代码可以运行之前进行所谓的“阐述”过程。 要做到这一点,最Ada编译创建一个特殊的入口点的方案,而不是仅仅使用你的“主”程序相关联的一个。 我想,蚋的是一样的东西C_yourprogramname ,但不要抱着我说。 即使要实现某种类型的库,制定应该(在某些特殊情况下,不适用于此execpt)运行第一。 但是,如果你想有一个程序来从阿达的外部调用的库程序,你一般不希望有一个“主”,所以有一些额外的步骤。 如何使用蚋做,这是他们的用户手册中描述 ,但一般涉及告诉编译器不会做一个“主”,呼吁adainit从外部运行任何阿达程序之前,并调用adafinal当你完成所有的工作。


文章来源: Loading Ada shared objects in Perl with DynaLoader.pm