是!
实际上,任何可以从C调用的语言都可以使用XS从Perl中使用.以下是如何使用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;
不要忘记更新MANIFEST.
我们现在写一下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();
从gnat文档我们知道我们需要调用adainit()并adafinal()初始化然后清理.这些调用环绕hello()在这里,但它们可能在XS文件中的某些其他函数中处于更好的位置.然后从Perl模块中的BEGIN和END块调用它们.
首先,我们不想将所有魔术链接和绑定委托给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~*
不要忘记更新MANIFEST.
最后,MakeFile.PL文件需要进行一些编辑.它必须调用上面的makefile来构建我们的库,然后在最后的链接阶段使用它.这是通过设置MYEXTLIB到src/hello.a并通过在添加规则postamble部分.
在我们的例子中,我们还需要链接libgnat(for Ada.Text_IO),它应该驻留在你系统的某个地方.这是通过编辑完成的LIBS.在这个例子中,路径是硬编码的,但你应该找出一种更便携的方法来查找libgnat.
use 5.018001;
use ExtUtils::MakeMaker;
# See lib/ExtUtils/MakeMaker.pm for details of how to influence
# the contents of the Makefile that is written.
WriteMakefile(
    NAME              => 'MyAdaModule',
    VERSION_FROM      => 'lib/MyAdaModule.pm', # finds $VERSION
    PREREQ_PM         => {}, # e.g., Module::Name => 1.1
    ($] >= 5.005 ?           # Add these new keywords supported since 5.005
      (ABSTRACT_FROM  => 'lib/MyAdaModule.pm', # retrieve abstract from module
       AUTHOR         => 'A. U. Thor <author@nonet>') : ()),
    DEFINE            => '',    # e.g., '-DHAVE_SOMETHING'
    INC               => '-I.', # e.g., '-I. -I/usr/include/other'
    LIBS              => ['-L/usr/lib/gcc/i686-pc-linux-gnu/4.8.2/adalib/ -lgnat'],
    MYEXTLIB          => 'src/hello.a',
);
sub MY::postamble {
    join("\n",
        "\$(MYEXTLIB)::",
        "\tmake -C src/",
        "",
        "clean::",
        "\tmake -C src/ clean",
    );
}
现在试试
$ perl Makefile.PL
$ make
$ make test
而且惊喜:测试没有通过!该hello()符号不存在.MyAdaLib.so使用该nm工具检查生成的make会显示某些符号已重命名.在我的情况下,他们的前缀是_ada_.所以我不得不打电话_ada_hello()而不是hello().这可以src/ada.ads使用Exportpragma 进行更正:
pragma Export
(Convention    => C,
 Entity        => hello,
 External_Name => "hello" );
根据我的理解,这应该对所有公共符号进行,因为它确保从C程序中理解类型,记录等的表示.
现在,你应该可以hello()从XSUB 打电话了.请享用!
| 归档时间: | 
 | 
| 查看次数: | 351 次 | 
| 最近记录: |