#概要
C++でdllを作ってPythonから呼ぶ方式を試してみる。
pybind11を使う版もやってみた↓
http://qiita.com/tibigame/items/499a81f0e1cb47962b90
#環境
- Windows7(64bit)
- Anaconda (Python3.6 64bit)
- Microsoft Visual C++ 2015 Community
#dll作成の流れ
- Visual C++ -> Win32コンソールアプリケーションを選んで ウィザードでdllを選択する。
- ビルドはReleaseでx64を選択
- 最初から開いているcppファイルにコードを記述
- ビルド(F7)
- 生成されたdllファイルをpythonコードがあるディレクトリにコピー
#C++コード
c++dll.cpp
#include "stdafx.h"
class ClassTest{
public:
int a;
int *b;
ClassTest() {
}
ClassTest(int X) {
a = X;
b = new int;
*b = X * 2;
}
~ClassTest() {
delete b;
}
int calcA(int add) {
return a + add;
}
int getB() {
return *b;
}
};
ClassTest **ClassTestArray;
// arrayNum個のクラスポインタ配列を確保する
extern "C" __declspec(dllexport) void initializeClass(int arrayNum) {
ClassTestArray = new ClassTest*[arrayNum];
}
// 終了時に呼ぶ
extern "C" __declspec(dllexport) void exitClass() {
delete[] ClassTestArray;
}
// index番目をXで初期化する
extern "C" __declspec(dllexport) void constructor(int index, int X) {
ClassTestArray[index] = new ClassTest(X);
}
// index番目を破棄
extern "C" __declspec(dllexport) void destructor(int index) {
delete ClassTestArray[index];
}
extern "C" __declspec(dllexport) int calcA(int index, int add) {
return ClassTestArray[index]->calcA(add);
}
extern "C" __declspec(dllexport) int getB(int index) {
return ClassTestArray[index]->getB();
}
#Pythonコード
test.py
from ctypes import cdll
import ctypes
# 作成したdllの読み込み
dll = cdll.LoadLibrary('./c++dll.dll')
# dllの関数をセット
initializeClass = dll.initializeClass
exitClass = dll.exitClass
constructor = dll.constructor
destructor = dll.destructor
calcA = dll.calcA
getB = dll.getB
#関数を呼び出す
initializeClass(5)
constructor(0, 100)
print (calcA(0, 10))
print (getB(0))
destructor(0)
exitClass()
#結果
110
200
かなり無理矢理関数化した感じだが、
コンストラクタで設定した100に
calcA()では10を足した110が
getB()では2倍にされた200が返っており期待通り。