python ctypes LoadLibrary로 windows dll 로드 및 함수 호출 예제
본 포스트는 python에서 ctypes의 LoadLibrary로 windows dll을 로드 하는 방법과 예제를 싣고 있다.
ctypes는 c 호환 데이터 형식을 제공하고 dll, 공유 라이브러리에서 함수를 호출할 수 있도록 해주는 python 라이브러리다. [https://docs.python.org/3.7/library/ctypes.html]
python에서 windows dll 로드 방법
import ctypes
ctypes.windll.LoadLibrary(name)
ctypes.oledll.LoadLibrary(name)
윈도우용 dll을 위의 두 API를 사용한다. 일반적인 dll을 로드 할 경우 WinDLL 인스턴스의 LoadLibary를 사용하고, OLE dll을 로드 할 경우 OleDLL 인스턴스의 LoadLibary를 사용한다.
dll 로드시 아래와 아래와 같은 에러가 발생할 경우가 있다. 이런 경우는 64 bits python 환경에서 win32로 빌드된 dll을 호출하거나, 32 bits python 환경에서 win64로 빌드된 dll을 호출해 발생하는 문제인 경우가 많다.
OSError: [WinError 193] %1은(는) 올바른 Win32 응용 프로그램이 아닙니다.
python에서 dll의 함수 호출 방법
python에서 windows dll의 함수 호출은 아래 dll 소스의 api 호출 예제를 통해 알아보자.
DEF 파일 없이 __declspec(dllexport) 키워드만 사용해 DLL의 함수를 export할 경우, python에서 함수를 인식하지 못하는 문제가 발생한다.
1. 일반적인 함수 호출
위 예제 dll의 xl_square는 아래 코드와 같이 호출할 수 있다.
dll = ctypes.windll.LoadLibrary('xl.dll')
xl_square = dll.xl_square # or xl_square = getattr(dll,'xl_square')
xl_square.argtypes = (ctypes.c_int,)
xl_square.restype = ctypes.c_int
result = xl_square(10)
LoadLibrary를 통해 dll을 불러온 후 반환되는 인스턴의의 attribute에 dll의 export된 함수가 생성되어 있으므로 위 예제처럼 바로 사용할 수도 있고, getattr을 통해 검색하여 불러올 수도 있다. argtypes 은 함수의 아규먼트 타입을 지정하며, ctypes type의 튜플 형태로 지정되어야 한다. restype은 함수의 리턴 타입을 지정한다.
ctypes의 type은 아래와 같다.
2. 포인터 아규먼트가 있는 함수 호출
포인터 아규먼트가 있는 xl_square_out 함수의 호출 방법은 아래와 같다.
dll = ctypes.windll.LoadLibrary('xl.dll')
xl_square_out = dll.xl_square_out
xl_square_out.argtypes =
(ctypes.c_int,ctypes.POINTER(ctypes.c_int))
xl_square_out.restype =
ctypes.c_int
result = ctypes.c_int()
xl_square_out(10,ctypes.byref(result))
argtypes 지정 시 포인터 아규먼트는 ctypes.POINTER를 사용하여 지정하고, 변수는 ctypes의 type으로 만든 후 함수 호출 시 ctypes.byref를 사용하면 된다.
3. callback 함수 포인터가 있는 함수의 호출
xl_callback 함수와 같이 함수 포인터가 있는 경우는 다음과 같이 호출할 수 있다.
dll = ctypes.windll.LoadLibrary('xl.dll')
callback_type = ctypes.WINFUNCTYPE(None,ctypes.c_int)
xl_callback = dll.xl_callback
xl_callback.argtypes = (callback_type,)
xl_callback.restype = None
def cb_func(val):
print('cb:',val)
xl_callback(callback_type(cb_func))
ctypes.WINFUNCTYPE을 사용하여 함수 포인터 형식을 만든다. argtypes에서는 만들어진 함수 포인터 형식을 사용한다. 함수 호출 시 def로 만들어진 함수를 함수 포인터 형식으로 변환해 호출한다.
위 python 예제 소스와 실행 결과는 다음과 같다.
import ctypes
class xldll(object):
def __init__(self):
self.dll = ctypes.windll.LoadLibrary('xl.dll')
self.xl_square = getattr(self.dll, 'xl_square')
#self.xl_square = self.dll.xl_square
self.xl_square.argtypes = (ctypes.c_int,)
self.xl_square.restype = ctypes.c_int
self.xl_square_out = self.dll.xl_square_out
self.xl_square_out.argtypes =
(ctypes.c_int,ctypes.POINTER(ctypes.c_int))
self.xl_square_out.restype = ctypes.c_int
self.callback_type =
ctypes.WINFUNCTYPE(None,ctypes.c_int)
self.xl_callback = self.dll.xl_callback
self.xl_callback.argtypes = (self.callback_type,)
self.xl_callback.restype = None
def cb_func(val):
print('cb:',val)
if __name__ == "__main__":
xl = xldll()
print(xl.xl_square(10))
result = ctypes.c_int()
print(result)
print(xl.xl_square_out(10,ctypes.byref(result)))
print(result)
xl.xl_callback(xl.callback_type(cb_func))
100
c_long(0)
0
c_long(100)
cb: 0
cb: 1
cb: 4
cb: 9
cb: 16
cb: 25
cb: 36
cb: 49
cb: 64
cb: 81
안녕 하세요
답글삭제파이썬으로 c++ dll 연동 코딩 중인에 막히는 부분이 있어서 그럽니다
개인적으로 도움 드려도 될까요
안녕하세요. 저도 문서 보고 공부하면서 간단한 예제만을 만들어본 정도라 도움이 될지 모르겠습니다. 막히는 부분을 알려주시면 최대한 아는 범위에서 답변드리도록 하겠습니다.
삭제안녕하세요..
답글삭제C++ dll 파일 함수를 파이썬 코드로 호출하는 소스를 작성중에 있습니다.
Ctypes로 dll파일을 불러오기까지는 성공은 했습니다만 내부 함수 기능을 사용하는 것에 막혀있습니다.
혹시 가능하시다면 몇가지 질문을 드려도 될까요..?
안녕하세요. 저도 문서 보고 공부하면서 간단한 예제만을 만들어본 정도라 도움이 될지 모르겠습니다. 막히는 부분을 알려주시면 최대한 아는 범위에서 답변드리도록 하겠습니다
삭제