3

最近 Ada の学習を始めました。Ada と C オブジェクト ファイルをリンクして多言語プログラムまたはライブラリを構築できることを知っています。XS を使用して Perl から Ada コードを呼び出すことは可能ですか?

4

1 に答える 1

9

はい!

実際、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 を更新することを忘れないでください。

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()andを呼び出しadafinal()て初期化してからクリーンアップする必要があることがわかります。これらの呼び出しはここで囲みhello()ますが、XS ファイル内の他の関数内のより適切な場所にある可能性があります。これらは、Perl モジュールの BEGIN および END ブロックから呼び出されます。

コンパイルする時間です!

エイダ図書館

まず、すべての魔法のリンクとバインドを MakeMaker に委任したくないので、src/ ディレクトリに Ada コードをコンパイルして静的ライブラリにする makefile を作成しましょう。

このライブラリを作成するhello.aには、ブヨのドキュメントに従うだけです。

  • およびgnatmake -cを生成するために使用します。hello.alihello.o
  • スイッチで使用hello.aliします。これにより、バインド コードを含むとが生成されます。gnatbind-nb~hello.adbb~hello.ads
  • b~hello.adbオブジェクトファイルにコンパイルします: b~hello.o.
  • グループ化しhello.ob~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.PL ファイルを編集する必要があります。上記の makefile を呼び出してライブラリをビルドし、最終的なリンク フェーズで使用する必要があります。これは、セクションにルールを設定MYEXTLIBして追加することによって行われます。src/hello.apostamble

Ada.Text_IOこの場合、システムのどこかにあるlibgnat (for ) とリンクする必要もあります。これは編集によって行われます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ツールを使用して make によって生成されたファイルを調べると、nm一部のシンボルの名前が変更されていることがわかります。私の場合、プレフィックスは_ada_. _ada_hello()そのため、代わりにを呼び出す必要がありhello()ます。これは、プラグマsrc/ada.adsを使用して修正できます。Export

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

私が理解したことから、これは、型、レコードなどの表現が C プログラムから理解されるようにするため、すべてのパブリック シンボルに対して行う必要があります。

hello()これで、XSUBから呼び出すことができるはずです。楽しみ!

于 2013-11-22T07:25:03.287 に答える