使用DynaLoader.pm在Perl中加载Ada共享对象 [英] Loading Ada shared objects in Perl with DynaLoader.pm

查看:329
本文介绍了使用DynaLoader.pm在Perl中加载Ada共享对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

长时间的监听者,首次调用者.我知道这是一个有点晦涩的问题,不要期望太大. :-)

Long time listener, first time caller. I'm aware this is a somewhat obscure question, and don't expect too much. :-)

我有以下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;

并将它们编译为共享对象,如下所示:

And compile them into a shared object like this:

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

这可以编译. nm显示以下符号:

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

现在,我尝试在Perl中加载该共享对象:

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:未定义符号:./greeter.pl第26行的__gnat_eh_personality.

有人有什么提示吗?我应该使用比DynaLoader更好/更容易的东西吗?

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:

推荐答案

在Perl方面我无能为力(您需要5.14,Mac OS X需要5.12,Debian 6需要5.10).也就是说,我可以帮助构建用于C main和直接链接的库...

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 ...

GNAT构建过程非常复杂,有两种工具可以支持它,gnatmakegprbuild. gnatmake可能会失去构建库的能力(2015年9月撰写),因此gprbuild是更好的选择.

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.

我认为您需要一个独立库项目(即,一个具有控制Ada详细说明的初始化和完成操作的项目;如果不初始化Ada库,则会得到SEGV或其他不良行为).您会发现构建一个

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.

我写的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.

The Library_Name attribute controls the name of the library; libgreeter.dylib on Mac OS X, libgreeter.so on Linux.

Library_Kind属性也可以是"static",在这种情况下,名称将是libgreeter.a.但是,独立库必须可重定位.

The Library_Kind attribute could alternatively be "static", in which case the name would be libgreeter.a. However, stand-alone libraries must be relocatable.

Library_Dir属性(必须提供上述两个属性)才能构成一个库,该属性控制库的创建位置.在这种情况下,在lib/中.

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/.

您必须提供Library_Interface属性以使其成为独立的库,并生成控制Ada详细说明的初始化和完成操作.它们分别称为 library_name init library_name final-在这里是greeterinitgreeterfinal.

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_nameinit and library_namefinal - here, greeterinit, greeterfinal.

如果Library_Auto_Init"false",则必须自己调用初始化和完成操作;如果"true",则将对其进行自动管理.

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说创建任何需要的输出目录",-P指定项目文件).

(-p says "create any needed output directories", -P specifies the project file).

我建造了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上)运行

and run (on Linux) using

$ LD_LIBRARY_PATH=./lib ./greeter

这篇关于使用DynaLoader.pm在Perl中加载Ada共享对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆