こんにちは、Perl 6 Advent Calendar 2016の20日目の投稿になります。
イントロダクション
皆さん、NativeCallを触ったことありますか?
NativeCallはPerl 6の世界とC/C++の世界をつなぐインタフェース、および、その実装です。
NativeCallを使った代表的なプログラムは、何度か紹介したInline::Perl5でしょう。
NativeCallを利用したプログラムを書いていると、エラーに遭遇した時にいったいどこに問題があるのかわけがわからなくなってしまうということがよくあると思います。
今回は、そんな時のために、NativeCallを使ったプログラムの一部だけを最小構成で再現する方法を紹介しようと思います。
具体的には、引数として与えられた文字列をそのままかえすecho
関数をCで実装して、Perl6から呼び出してみます。
準備
- ディレクトリの作成
$ mi6 new MyNative # mi6 はpandaかzefで入れてください
$ mv MyNative p6-MyNative
$ cd p6-MyNative
- rakudoのリポジトリの中の、
CompleTestLib.pm
(※)をwget
でとってきましょう
$ cd t
$ wget https://raw.githubusercontent.com/rakudo/rakudo/nom/t/04-nativecall/CompileTestLib.pm
-
エディタで
CompileTestLib.pm
を開いて編集します -
t/04-nativecall/$name
となっているところをすべてt/$name
に置き換えます。 -
保存します
-
C言語のヘッダファイルとコード本体を生成します
$ touch example.c
$ touch example.h
- ディレクトリ構成を確認すると、このようになっているはずです:
$ tree
.
├── LICENSE
├── META6.json
├── README.md
├── bin
├── lib
│ └── MyNative.pm6
└── t
├── 01-basic.t
├── CompileTestLib.pm
├── example.c
└── example.h
コードを書いていきましょう
- 下記の例では、入力された文字列をそのまま返すだけの単純な関数
echo
を実装しています
t/01-basic.t
-
01-basic.t
を下記のように編集して保存してみましょう
use v6;
use Test;
use MyNative;
use NativeCall;
use lib <lib t>;
use CompileTestLib;
compile_test_lib('example');
my sub echo(Str $msg) returns Str is native('./example') { * }
is echo("Qiita"), "Qiita";
done-testing;
t/example.h
-
example.h
を下記のように編集して保存してみましょう
#if ! defined(HEADER_EXAMPLE_H)
#define HEADER_EXAMPLE_H
#ifdef __cplusplus
extern "C" {
#endif
const char* echo(const char* msg);
#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif
#endif /* HEADER_EXAMPLE_H */
t/example.c
-
example.c
を下記のように編集して保存してみましょう
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "example.h"
#ifdef _WIN32
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT extern
#endif
const char* echo(const char* msg) {
return msg;
}
実行
- 実行してみましょう
$ mi6 test -v t/01-basic.t
...
t/01-basic.t ..
ok 1 -
1..1
ok
All tests successful.
よさそうです。このような要領で、挙動を確認してみたい箇所のコードだけをコンパイルして実行するということが可能になります。
脚注
(※) CompleTestLib.pm is licensed under the Artistic License 2.0
以上、Perl 6 Advent Calendar 2016の20日目の投稿でした。
21日目は@magnolia_k_ さんの担当となります。それではお楽しみに!