3
1

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.

vlang から C 関数を呼ぶ(c interop)

Last updated at Posted at 2020-02-09

背景

C/C++ メインのグラフィックスアプリやグラフィックスライブラリがある.

スクリプト系言語でバインディングを書きたい. UI を作りたいとか, ユニットテストとかでパラメータをいじったりをスクリプト側で行いたいなど.
元々グラフィックス用向けを想定して開発されていたらしい vlang を使ってみる.

hot code reloading とか, graphics 周りに強いのをアピール(W.I.P だが)しています.

vlang について

OpenGL binding とかが標準であります. go ライクで型付きで, gc が無いので素晴らしいですね.
(gc なしにいろいろうまく処理するのはまだ作業途中ですが)

基本 C compiler(gcc とか)に丸投げっぽい感じで処理していて, 本体は軽くてよい(LLVM とかつかっていない)

vlang 自体が C に変換してコンパイルして実行してる(はず)ので, C との親和性は高いと想像します.

C 関数を呼ぶ

Windows を含む cross platform を謳っていますが, ここでは Linux 環境を想定します.

C/C++ ユーザーからすれば, 比較的すんなり理解できると思います.

複雑な struct は難しいかもしれませんので, C レイヤーのほうで完結なデータ構造にしておくのが吉です.


# pragma once

# ifdef __cplusplus
extern "C" {
# endif

int myfunc(int x, int y);

# ifdef __cplusplus
}
# endif

こんなかんじでヘッダーを用意して,

# include "mylib.h"

int myfunc(int y, int x)
{
  return x + y;
}

こんな感じで実体を書いて,

$ gcc -o libmylib.so -shared -c mylib.cc

とコンパイルして,

// test.v
# flag -I.
# flag -L.
# flag -lmylib
# include "mylib.h"

fn C.myfunc(x int, y int) int

fn main() {
	n := C.myfunc(3, 4)
    println(n)
}
$ ../v run test.v 
7

voala!

エラーが出る場合は,

$ v -show_c_cmd test.v
==========
cc  -std=gnu11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-unused-result -Wno-unused-function -Wno-missing-braces -Wno-unused-label -Werror=implicit-function-declaration -o "/home/syoyo/work/v/sandbox/test" "/home/syoyo/.cache/v/test.tmp.c"  -I "/home/syoyo/work/v/sandbox" -L "/home/syoyo/work/v/sandbox" -lmylib  -lm -lpthread   -ldl 
cc took 916 ms
=========

として, どのように内部でリンクなどの呼び出しが行われれているか確認できます!

Windows(llvm-mingw) で動かす.

llvm-mingw と組み合わせてみます.

とりあえず llvm-mingw だと, MSVC と同様に, import lib を作らないとリンクできないことがわかりました.

/d/local/llvm-mingw/bin/gcc -shared -o mylib.dll mylib.cc -Wl,--output-def,foo.def
/d/local/llvm-mingw/bin/llvm-dlltool -m i386:x86-64 -d foo.def -l foo.lib -D mylib.dll

という風にすればいけます!
最近の llvm-dlltool ですと, -D で dll ファイル指定も必要でした.

./v.exe -g -show_c_cmd -cc /d/local/llvm-mingw/bin/gcc.exe run test.v         
==========
D:/local/llvm-mingw/bin/gcc.exe  -std=gnu11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-unused-result -Wno-unused-function -Wno-missing-braces -Wno-unused-label -g3 -no-pie -Werror=implicit-function-declaration -o "test.exe" "C:\Users\syoyo\AppData\Local\Temp\v\test.tmp.c" -municode  -ldbghelp -I "C:\Users\syoyo\local\v_windows" -L "C:\Users\syoyo\local\v_windows" -lmylib
=========

7

Voala!

TODO

  • C コードに, dllimport, dllexport も記載しておくとよいか?
  • import lib 作成用の .def を別コマンドで行う(.dll から抜き出す方法を調べる)

まとめ

なんだかいい感じに C と連携できそうなので, Patoreon で vlang プロジェクト(実質的にはひとりで開発している?)に課金したくなってきますね! :money_mouth:

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?