C++でライブラリー(DLL)を作り、pythonなどから利用する方法について連載します。
1. C++でライブラリーを作る Linux編
2. pythonからC++のライブラリーを利用する Linux編
3. C++でライブラリー(DLL)を作る Windows編
4. pythonからC++のライブラリー(DLL)を利用する Windows編
5. C#からC++のライブラリー(DLL)を利用する
6. python・C#とC++間で複素数を受け渡す
このページではpythonから上記3.にてC++で作成したDLLを利用する方法について説明します。
概要
上記2.のLinux版pythonとの相違点は2つあります。
1点めはLoadLibrary()の引数であるライブラリー(DLL)のパスが、Linuxでは ./ でしたが、Windowsでは os.getcwd() で得たパスになります。
2点めは文字列のエンコードデコードにLinuxではutf-8、Windowsではmbcsを指定しています。半角文字だけならWindowsでutf-8でも動いてくれるようです。
その他のコードの詳細につきましては、上記2.のLinux版pythonの説明をご覧下さい。
サンプルコード
import os
import sys
import ctypes
class tagLibParameter(ctypes.Structure):
_fields_ = [("dInA", ctypes.c_double),
("dInB", ctypes.c_double),
("dOut", ctypes.c_double),
("sData", ctypes.c_char * 64)]
def main(argv):
#----------------
global LLib
#----------------
path = os.getcwd()
sFnDll = path + '\\LocalLib.dll'
LLib = ctypes.cdll.LoadLibrary(sFnDll)
#================================================================
nA = 1
nB = 2
#---------------------
nRet = LLibSum(nA, nB)
#---------------------
print('%d + %d = %d' % (nA, nB, nRet))
#================================================================
dsArray = ctypes.c_double * 3
dsIn = dsArray()
dsOut = dsArray()
dsIn[0] = 1.1
dsIn[1] = 2.2
dsIn[2] = 3.3
#--------------------------
LLibCalcX10(dsOut, dsIn, 3)
#--------------------------
print('in[%.1lf %.1lf %.1lf] out[%.1lf %.1lf %.1lf]' % (\
(dsIn[0]), (dsIn[1]), (dsIn[2]),\
(dsOut[0]), (dsOut[1]), (dsOut[2]) ))
#================================================================
sRxBuf = ctypes.create_string_buffer(256)
sTxBase = 'App->DLL: Hello !'
sTxBuf = sTxBase.encode('mbcs')
#-----------------------------------
LLibTxRxMessage(sRxBuf, sTxBuf, 256)
#-----------------------------------
print('%s' % (sRxBuf.value.decode('mbcs')))
#================================================================
LP = tagLibParameter()
(LP.dInA) = 1.1
(LP.dInB) = 2.2
#-----------------------------
LLibInOutStr(ctypes.byref(LP))
#-----------------------------
print('%.1lf + %.1lf = %.1lf [%s]' % (\
(LP.dInA), (LP.dInB), (LP.dOut), (LP.sData.decode('mbcs'))))
def LLibSum(nInA, nInB):
LLib.LLibSum.argtypes = (ctypes.c_int, ctypes.c_int)
LLib.LLibSum.restype = ctypes.c_int
#--------------------------------
nRet = LLib.LLibSum(nInA, nInB)
#--------------------------------
return nRet
def LLibCalcX10(dpOut, dpIn, nInLen):
LLib.LLibCalcX10.argtypes = (ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int)
LLib.LLibCalcX10.restype = ctypes.c_int
#--------------------------------
nRet = LLib.LLibCalcX10(dpOut, dpIn, nInLen)
#--------------------------------
return nRet
def LLibTxRxMessage(bpOut, bpIn, nInLen):
LLib.LLibTxRxMessage.argtypes = (ctypes.c_char_p, ctypes.c_char_p, ctypes.c_int)
LLib.LLibTxRxMessage.restype = ctypes.c_int
#--------------------------------
nRet = LLib.LLibTxRxMessage(bpOut, bpIn, nInLen)
#--------------------------------
return nRet
def LLibInOutStr(sp):
LLib.LLibInOutStr.argtype = ctypes.c_void_p
LLib.LLibInOutStr.restype = ctypes.c_int
#--------------------------------
nRet = LLib.LLibInOutStr(sp)
#--------------------------------
return nRet
if __name__ == '__main__':
main(sys.argv)
実行例
CallLib.pyとLocalLib.dllを同じディレクトリーに置いて実行して下さい。
pythonとライブラリーの間で、変数・配列・文字列・構造体の双方向のやりとりが出来ています。
冒頭3.のC++で作った呼び出し側のサンプルコード実行時と同じ結果です。
D:\>python CallLib.py
start DLL
1 + 2 = 3
in[1.1 2.2 3.3] out[11.0 22.0 33.0]
DLL->App: Hi ! rcvd[App->DLL: Hello !]
1.1 + 2.2 = 3.3 [2025 11/21 11:54:29 017]
end DLL