x10からC++の関数を呼ぶ にある方法でC++の関数を呼ぶことができる。
ただし、ここに記載されているのは引数が以下の3通りについてのみ。
- プリミティブ型(Long, Doubleなど)
- プリミティブ型の配列
- 文字列
ここでは「文字列の配列」を引数とするC++の関数をどのように呼べばよいかを説明する。
コード
まずコードを示す。
import x10.io.Console;
import x10.compiler.Native;
import x10.compiler.NativeCPPInclude;
import x10.compiler.NativeCPPCompilationUnit;
@NativeCPPInclude("MyCpp.hpp")
@NativeCPPCompilationUnit("MyCpp.cpp")
class Main {
public static def main( args: Rail[String] ) {
nativeFunc( args );
}
@Native("c++", "nativeFunc( #1 )")
native static def nativeFunc( argv: Rail[String] ): void;
}
#include <x10/lang/Rail.h>
#include <x10/lang/String.h>
void nativeFunc( x10::lang::Rail<x10::lang::String*>* argv );
#include <x10/lang/Rail.h>
#include <x10/lang/String.h>
void nativeFunc( x10::lang::Rail<x10::lang::String*>* argv ) {
for( size_t i=0; i < argv->FMGL(size); i++ ) {
x10::lang::String* x10_str = argv->raw[i];
std::cerr << x10_str->c_str() << std::endl;
}
}
以上のコードを同じディレクトリに配置し、x10c++ -d build rail_string.x10
でコンパイルすればよい。
例えば、./build/a.out foo bar
というコマンドを実行すると、foo\nbar
と出力される。
解説
通常のC++関数呼び出しと同じように @Native
を付与した関数を呼ぶ。
@Native("c++", "nativeFunc( #1 )")
native static def nativeFunc( argv: Rail[String] ): void;
C++の関数が呼ばれるが、プリミティブ型ではないクラスを引数に渡した場合、それらに対応するx10オブジェクトのポインタが渡される。
具体的には、Rail[String]
を引数として渡すと、C++側での型は x10::lang::Rail<x10::lang::String*>*
となる。
ちなみにRail,StringのC++のクラス定義は以下のファイルを見ればよい。
https://github.com/x10-lang/x10/blob/master/x10.runtime/src-cpp/x10/lang/Rail.h
https://github.com/x10-lang/x10/blob/master/x10.runtime/src-cpp/x10/lang/String.h
あとはC++側でこれらのオブジェクトを操作していく。
x10::lang::Rail
クラスの主要なメソッドは以下の通り
-
argv->FMGL(size)
: size属性を取得する- FMGLというのはマクロ。Railに限らずx10の属性にアクセスする時には
FMGL(属性名)
という操作を行えばアクセスできる。
- FMGLというのはマクロ。Railに限らずx10の属性にアクセスする時には
-
raw
: 配列の実体- 例えば
argv->raw[0]
とすると、最初の要素にアクセスできる。
- 例えば
x10::lang::String
クラスの主要なメソッドは以下の通り
-
c_str()
: 文字列のポインタ (const char*) を返す。c++のstd::string#c_str()
と同じ。
これらを使うと文字列の配列を操作して、一般的なC++の文字列の配列にすることができる。
MyCpp.cppで実装をC++で定義する際に
#include <x10/lang/Rail.h>
#include <x10/lang/String.h>
を忘れるとエラーになる。
ちなみにx10c++
コマンドでコンパイルすると、x10/lang
までのパスがincludeパスに含まれるので、自分で明示的にこれらのパスを指定する必要はない。
またこれを応用すれば、x10の標準ライブラリに含まれる別のクラスについても同じようにC++の関数に渡すことができるだろう。