如何在使用XS的Perl程序中使用Ada模块?

如何在使用XS的Perl程序中使用Ada模块?,perl,gcc,ada,gnat,xs,Perl,Gcc,Ada,Gnat,Xs,我最近开始学习Ada,知道Ada和C对象文件可以用来构建多语言程序或库,是否可以使用XS从Perl调用Ada代码?是的 事实上,任何可以从C调用的语言都可以从Perl使用XS。下面是一个如何使用Ada模块和ExtUtils::MakeMaker实现的解决方案 摆设 模块树 让我们首先使用h2xs创建一个模块树: $ h2xs -A -n MyAdaModule 然后,让我们创建一个子目录来保存Ada文件: $ cd MyAdaModule $ mkdir src 这是模块的规范:src/he

我最近开始学习Ada,知道Ada和C对象文件可以用来构建多语言程序或库,是否可以使用XS从Perl调用Ada代码?

是的

事实上,任何可以从C调用的语言都可以从Perl使用XS。下面是一个如何使用Ada模块和ExtUtils::MakeMaker实现的解决方案

摆设 模块树 让我们首先使用
h2xs
创建一个模块树:

$ h2xs -A -n MyAdaModule
然后,让我们创建一个子目录来保存Ada文件:

$ cd MyAdaModule
$ mkdir src
这是模块的规范:src/hello.ads

procedure hello;
。。。正文:src/hello.adb

with Ada.Text_IO;
use Ada.Text_IO;

procedure hello is
begin
    Put_Line("Hi from Ada!");
end;
别忘了更新清单

写入XS文件 现在让我们编写MyAdaModule.xs的主体。这非常类似于使用C库中的函数:

#define PERL_NO_GET_CONTEXT
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "ppport.h"

extern void adainit();
extern void adafinal();

MODULE = MyAdaModule        PACKAGE = MyAdaModule       

void say_hello()
    CODE:
        adainit();
        hello();
        adafinal();
从中我们知道我们需要调用
adainit()
adafinal()
来初始化并清理。在这里,这些调用围绕着
hello()
,但在XS文件中的其他函数中,它们可能位于更好的位置。然后从Perl模块中的开始和结束块调用它们

该编译了! Ada图书馆 首先,我们不想将所有神奇的链接和绑定委托给MakeMaker,所以让我们在src/目录中创建一个makefile,将Ada代码编译成一个静态库

要创建此库,
hello.a
,我们只需遵循gnat文档:

  • 使用
    gnatmake-c
    生成
    hello.ali
    hello.o
  • 使用
    hello.ali
    gnatbind
    以及
    -n
    开关。这将生成包含绑定代码的
    b~ hello.adb
    b~ hello.ads
  • b~hello.adb
    编译成一个对象文件:
    b~hello.o
  • hello.o
    b~ hello.o
    组合到一个存档中,与
    ar
简而言之,我们将使用这个makefile:

all: hello.a

hello.a: hello.o b~hello.o
    ar rcs $@ $^

hello.o: hello.adb hello.ads
    gnatmake -c -o $@ $<

b~hello.o: b~hello.adb b~hello.ads
    gnatmake -c -o $@ $<

b~hello.adb: hello.ali
    gnatbind -n $<

hello.ali: hello.o

clean:
    rm -rf *.o *.ali *.a b~*
现在试试

$ perl Makefile.PL
$ make
$ make test
令人惊讶的是:考试没有通过!
hello()
符号不存在。使用
nm
工具检查make生成的
MyAdaLib.so
,发现一些符号已重命名。在我的例子中,它们的前缀是
\u ada\u
。所以我必须调用
\u ada\u hello()
而不是
hello()
。这可以在
src/ada.ads
中使用
Export
pragma进行更正:

pragma Export
(Convention    => C,
 Entity        => hello,
 External_Name => "hello" );
据我所知,这应该适用于所有公共符号,因为它确保类型、记录等的表示可以从C程序中理解

现在,您应该能够从XSUB调用
hello()
。享受吧

pragma Export
(Convention    => C,
 Entity        => hello,
 External_Name => "hello" );