読者です 読者をやめる 読者になる 読者になる

Perl - XSでDLLを呼び出す(その6)

今回は渡された文字列を返すサブルーチンを実装する。

渡された文字列を返す

引き数で指定された文字列をそのまま返すサブルーチンをExample2.xsに追加で実装する。

char *
echo_pv(s)
INPUT:
    char *s;
CODE:
    RETVAL = s;
OUTPUT:
    RETVAL

以下の点がecho_ivやecho_nvサブルーチンと異なる。
戻り値のタイプはC言語と同じ文字列のポインタを表す "char *" である。
なぜか、"IV" や "NV" と同様の "PV" の定義が無い。
INPUTフィールドに記述する "s" のタイプは戻り値と同様に "char *" である。

テストのために以下のスクリプトを "c:\xs\Example2\TestEx2-3.pl" として保存する。

use ExtUtils::testlib;
use Example2;

print Example2::echo_pv(123) . "\n";
print Example2::echo_pv(456.789) . "\n";
print Example2::echo_pv("012") . "\n";
print Example2::echo_pv("345.678") . "\n";
print Example2::echo_pv("901.234yen") . "\n";
print Example2::echo_pv("hello world") . "\n";
print eval {Example2::echo_pv()};
print $@;
print eval {Example2::echo_pv(5, "hello")};
print $@;

上記を実行した結果は以下の通りである。

123
456.789
012
345.678
901.234yen
hello world
Usage: Example2::echo_pv(s) at TestEx2-3.pl line 10.
Usage: Example2::echo_pv(s) at TestEx2-3.pl line 12.

当然、結果は全てが文字列として扱われた。
Cファイルの内容はどうだろうか。

XS(XS_Example2_echo_pv)
{
    dXSARGS;
    if (items != 1)
        Perl_croak(aTHX_ "Usage: Example2::echo_pv(s)");
    {
        char *  s = (char *)SvPV_nolen(ST(0));
        char *  RETVAL;
        dXSTARG;
#line 36 "Example2.xs"
        RETVAL = s;
#line 173 "Example2.c"
        sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
    }
    XSRETURN(1);
}

以下の点がecho_ivやecho_nvサブルーチンと異なる。
SvPV_nolenマクロはSTマクロの戻り値を文字列に変換するようだ。
RETVAL変数はecho_pvサブルーチンの戻り値のタイプで定義されている 。
どこか(手掛かりはインクルードヘッダとdXSARGS、dXSTARGマクロ)でTARG変数が定義されており、sv_setpvマクロはこのTARG変数にRETVALが指す文字列を設定するようだ。
そして、PUSHTARGマクロによってTARG変数をスタックに積むようだ。

次回はここまでに分かったことのまとめを行おうと思う。