LoginSignup
9
5

More than 5 years have passed since last update.

Juliaの配列をFFIで渡す

Last updated at Posted at 2019-01-27

準備

今回はC++で生成した共有ライブラリをJuliaから呼び出す形で実験します。

cmake_minimum_required(VERSION 2.8)
add_library(myffi SHARED
  ffi.cpp
  )
set_target_properties(myffi PROPERTIES PREFIX "")

共有ライブラリはcmakeで生成します。以下でのべるC++コードはffi.cppとして保存します。
ビルドした共有ライブラリはそのままだとJuliaが見つけられないと思うのでLD_LIBRARY_PATHで指定してください。

cmake .
make     # これでmyffi.soができるので、これを探せるようにする
LD_LIBRARY_PATH=$PWD julia main.jl

ポインタで渡す場合

Calling C and Fortran Codeを参考に実装します。

extern "C" {

void make_twice_ptr(int n, float *p) {
  for (int i = 0; i < n; ++i) {
    p[i] *= 2.0;
  }
}
}

これをJuliaから呼び出します:

a = ones(Float32, 2, 3)
ccall((:make_twice_ptr, "myffi"), Cvoid, (Int32, Ptr{Float32}), 2*3, a)
println(a)

JuliaからFFIをccallで呼び出すとき、Julia側で一旦変換が実行されてから渡されます。

Array{T,N}
When an array is passed to C as a Ptr{T} argument, it is not reinterpret-cast: Julia requires that the element type of the array matches T, and the address of the first element is passed.

とある通り、Julia側の配列型のアドレスをポインタにするのではなく、データの最初の位置を指すポインタに変換されてわたされるのでこれでちゃんと動作します

Float32[2.0 2.0 2.0; 2.0 2.0 2.0]

構造体として渡す場合

Embedding Juliaを参考に実装します。

#include <julia/julia.h>

extern "C" {

void make_twice_array(jl_value_t *ptr) {
  if (jl_is_array_type(ptr) != 0) {
    std::cerr << "This is not an array." << std::endl;
    return; // TODO Error handling
  }
  auto array = reinterpret_cast<jl_array_t *>(ptr);

  if (array->elsize != sizeof(float)) {
    std::cerr << "This is not a float array." << std::endl;
    return; // TODO Error handling
  }

  float *data = reinterpret_cast<float *>(array->data);
  for (size_t i = 0; i < array->length; ++i) {
    data[i] *= 2.0;
  }
}
} // extern C
b = ones(Float32, 2, 3)
ccall((:make_twice_array, "myffi"), Cvoid, (Any,), b)
println(b)

こちらはAnyとして渡してしまって、C++側でJuliaのAPIを使用して型を判定してreinterpret_castで変換します。JuliaのAPIはイマイチどこにドキュメントがあるか分からなかったので/usr/include/julia/julia.hにインストールされたヘッダーをそのまま見て書いてます。

最後に

課題

  • C++の例外をJuliaに渡す部分
  • Juliaのパッケージの一部としてC++の拡張機能を配布する方法

今回のコードは以下に置いておきます:
https://github.com/termoshtt/julia_ffi_example

9
5
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
9
5