0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Perl 6Advent Calendar 2016

Day 20

NativeCallを使ったプログラムの一部だけを最小構成で再現する方法

Posted at

こんにちは、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_ さんの担当となります。それではお楽しみに!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?