この記事は?
C向けSDKが手元にあるけど柔軟にインタプリタ型言語のPythonでチクチク触りたい人向に刺さると思われる記事です。
時間がない人向け
ctypeslib2をインストールすると付属するclang2pyを使用すると簡単にできる
pip install ctypeslib2
clang2py header.h -o out.py
- (Windowsのみ)生成されたコードを編集し、DLLとリンク
確認のためCソースから自作してPythonから呼んでみる
XとYの値を持つPOINT
型を含んだヘッダファイルを作ります。
C言語側のお仕事はprint_position()
でPOINT
の属性を出力すること。
DLL化するために__declspec(dllexport)
を使用します。
point.h
#ifndef POINT_H
#define POINT_H
typedef struct Point {
int x;
int y;
} Point;
__declspec(dllexport) void print_position(Point *);
#endif
point.c
#include "point.h"
#include <stdio.h>
void print_position(Point *point) { printf("X:%d, Y:%d", point->x, point->y); }
動的ライブラリを作る
cl -LD .\point.c
この地点でdllとlibが生成されれば成功。
clang2pyでcヘッダを変換
pip install ctypeslib2
clang2py.exe .\point.h > point.py
生成されたバインディングにDLLを紐づける
生成結果には以下のような行があるはずです。
point.py
# libraries['FIXME_STUB'] explanation
# As you did not list (-l libraryname.so) a library that exports this function
# This is a non-working stub instead.
# You can either re-run clan2py with -l /path/to/library.so
# Or manually fix this by comment the ctypes.CDLL loading
_libraries = {}
_libraries['FIXME_STUB'] = FunctionFactoryStub() # ctypes.CDLL('FIXME_STUB')
これをこう書き換えます。
point.py
# libraries['FIXME_STUB'] explanation
# As you did not list (-l libraryname.so) a library that exports this function
# This is a non-working stub instead.
# You can either re-run clan2py with -l /path/to/library.so
# Or manually fix this by comment the ctypes.CDLL loading
_libraries = {}
_libraries['FIXME_STUB'] = ctypes.WinDLL(r'path\to\point.dll')
dllが一つならばリンクするキーはFIXME_STUB
のままでいい気もします。 linuxならclang2pyの-lオプションで自動でやってくれるかもしれないです。
pythonから呼び出してみる
構造体を作ってprint_position
に参照渡しする。
main.py
import ctypes
import point
p = point.Point()
p.x = 100
p.y = 200
point.print_position(ctypes.byref(p))
成功例
成功していればcのソースに従ってX,Yのポイントが出力されます。
感想
フィールドが補完されないのがちょっとつらいです。
あとメモリダンプをデバッガから確認しづらいのも苦しいです。