はじめに
前回のPythonからDLLを使うの続き
クラスはどうやって使うのかなって思ったので、調べながら進めました。
C++でDLLの準備
VS2017で、前回のようにDLLのプロジェクトを作る。今回のプロジェクト名は「DLLTestClass」としました。
#pragma once
#ifdef DLLTESTCLASS_EXPORTS
#define DLLTESTCLASS_API extern "C" __declspec(dllexport)
#else
#define DLLTESTCLASS_API extern "C" __declspec(dllimport)
#endif // DLLTEST_EXPORTS
class Hoge
{
private:
int m_count;
public:
Hoge();
const wchar_t* showMessage(const wchar_t* message);
void count();
void showCount();
};
DLLTESTCLASS_API const wchar_t* showMsg(const wchar_t* mes);
DLLTESTCLASS_API void countData();
DLLTESTCLASS_API void showCount();
// DLLTestClass.cpp : DLL アプリケーション用にエクスポートされる関数を定義します。
//
#include "stdafx.h"
#include "DLLTestClass.h"
#include <iostream>
#include <string>
Hoge::Hoge()
{
m_count = 0;
}
const wchar_t* Hoge::showMessage(const wchar_t* message)
{
return message;
}
void Hoge::count()
{
m_count = m_count + 1;
}
void Hoge::showCount()
{
std::cout << m_count << std::endl;
}
/* ラッパー */
Hoge hoge;
const wchar_t* showMsg(const wchar_t* mes)
{
return hoge.showMessage(mes);
}
void countData()
{
hoge.count();
}
void showCount()
{
hoge.showCount();
}
// stdafx.h : 標準のシステム インクルード ファイルのインクルード ファイル、
// または、参照回数が多く、かつあまり変更されない、プロジェクト専用のインクルード ファイル
// を記述します。
//
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Windows ヘッダーからほとんど使用されていない部分を除外する
// Windows ヘッダー ファイル
#include <windows.h>
// プログラムに必要な追加ヘッダーをここで参照してください
#include "DLLTestClass.h"
C++側の実装はこんな感じ。そのままビルド通ると思います。
よくわかってない中進めていたのですが、ラッパー関数を作ってあげないと、うまく使えないっぽい??(こういうもんなんですかね?)
何か別のライブラリを加えれば、python側でスマートに呼べるみたいなのだけど、、、、ちょっと何を言ってるのかわからないです。
とりあえず、python側でcountData()を呼べばカウントがガシガシ行われるようにしてみました。(恐る恐る)
Python側を作る
VSでビルドしたDLLをPython側の環境に持ってきます。(DLLTestClass.dll)
# coding: utf-8
from ctypes import *
dll2 = cdll.LoadLibrary("DLLTestClass.dll")
# 文字列セット
txt = u"あいうえ"
dll2.showMsg.argtypes = [c_wchar_p]
dll2.showMsg.restype = c_wchar_p
print(dll2.showMsg(txt))
# 加算
dll2.countData()
dll2.countData()
dll2.countData()
dll2.countData()
# 表示
dll2.showCount()
実行結果
> py test.py
あいうえ
4
テキスト入力して、返ってきて、ちゃんとカウントが4回行われて、表示されました。
ほんと、c_wchar_pの書き方とかググるだけでは本当によくわからなくて時間かかりました。
文字列を受け取って、返す流れとか文字化けとかの戦いでした。検索ワードがよくなかったのかなあ。。
クラスを実行するのよりマルチバイト文字列のところが時間かかりました。
何が正しくて何が正しくないのか謎でしたが、今回ひとまず動いたのでヨシとしようと思います。