はじめに
あることから、PythonでC++で作られたDLLを読み込みたいので調べる必要が出てきました。
私自身PythonもC++もさわり程度しか知らないため、少しハマりました。
様々な記事が既に世の中に存在していますが、自分のために書き残そうと思います。
まずDLLを準備
VS2017 使用しています。
ダイナミックリンクライブラリのプロジェクトを作成。名前は何でもいいと思います。
今回はDLLTestという名前で作っています。
DLLプログラムを作っていきます
#pragma once
#ifdef DLLTEST_EXPORTS
#define DLLTEST_API extern "C" __declspec(dllexport)
#else
#define DLLTEST_API extern "C" __declspec(dllimport)
#endif // DLLTEST_EXPORTS
DLLTEST_API int GetData(int, int);
extern "C" __declspec(dllexport)
で、関数のエクスポート宣言をします。
// DLLTest.cpp : DLL アプリケーション用にエクスポートされる関数を定義します。
//
#include "stdafx.h"
#include "DLLTest.h"
int GetData(int a, int b)
{
return a + b;
}
実行する関数を作っていきます。
// stdafx.h : 標準のシステム インクルード ファイルのインクルード ファイル、
// または、参照回数が多く、かつあまり変更されない、プロジェクト専用のインクルード ファイル
// を記述します。
//
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // Windows ヘッダーからほとんど使用されていない部分を除外する
// Windows ヘッダー ファイル
#include <windows.h>
#include <string>
// プログラムに必要な追加ヘッダーをここで参照してください
#include "DLLTest.h"
はい、以上です。ハマりどころは後述します。先に成功パターンで。
Debugビルドを行ってDLLを作成します。DLLはプロジェクトの中のDebugフォルダの中にあります。
次にPython側で呼び出し
PCにはPython 3.7と2.7がインストールされていますが、3.7を今回利用しています。
VS2017で作ったDLLをpythonのソースの場所へコピーしてきます。
そして、LoadLibraryにDLL名をセットします。
# coding: utf-8
from ctypes import *
dll = cdll.LoadLibrary("DLLTest.dll")
print(dll.GetData(100, 101))
これで、Pythonを実行すると。DLLで結果を出すことができました。
> py test.py
201
ハマったところ
「OSError: [WinError 193] %1 は有効な Win32 アプリケーションではありません。」と出た。
解決
DLLのビルドがx64ではなかった。Pythonを64ビットでインストールしてたため。気づくのに少し時間かかりました。。
「AttributeError: function 'GetData' not found」と出た。
解決
extern "C"が抜けていた。
#define DLLTEST_API extern "C" __declspec(dllexport)
いろいろ勉強になりました。