Let's compile Python Source Code into DLL using Python Embedding
by Qerogram서론
누리랩에서 공개한 "초간단 실시간 감시기 만들기(3)"(https://nurilab.github.io/2020/06/01/kicomav_driver_3) 포스팅에서 Python Embedding을 접하게 되었다. 개념은 알고 있었지만, 찾아봐도 이해가 잘 안되서 삽질을 꽤 많이 했다. 추후에도 이용할 것 같아서 간단하게 정리해서 공유하려고 한다.
Goal
Python Embedding을 통해 DLL 파일로 만들어서, C 계열로 작성된 다른 모듈에도 사용하자.
Requirement
"pyc"라는 확장자를 가진 컴파일된 파이썬 파일 혹은 파이썬 소스코드, Visual Studio, Python이 필요하다.
Set Environment
우선 IDE에서 프로젝트(DLL)를 하나 만든 뒤 Embedding을 할 수 있게끔, 관련 설정을 해준다.
[솔루션 뷰] -> [프로젝트] 명 우클릭 -> [속성] -> [구성 속성] -> [VC++ 디렉터리]로 이동한 뒤,
포함 디렉터리, 참조 디렉터리에 각각 %PythonPath%\Include, %PythonPath%\libs를 추가한다.
이후, [링커] -> [입력] -> 추가종속성에 python[버전].lib (세부 빌드는 중요하지 않음, 2.7.18 -> 2.7, 3.8.2 -> 3.8 등)을 추가한다.
How To
1. Python Code를 작성한다. 해당 함수가 호출되면, 메세지 박스가 나타나게 된다.
# qerogram.py
from ctypes import c_int, WINFUNCTYPE, windll
from ctypes.wintypes import HWND, LPCSTR, UINT
prototype = WINFUNCTYPE(c_int, HWND, LPCSTR, LPCSTR, UINT)
paramflags = (1, "hwnd", 0), (1, "text", "Hi"), (1, "caption", None), (1, "flags", 0)
def hello_qerogram() :
MessageBox = prototype(("MessageBoxA", windll.user32), paramflags)
2. DLL을 작성한다. 설명이 필요한 부분은 아래와 같이 주석으로 작성해뒀으므로 참조.
// DLL SourceCode
#include "pch.h"
#include "Python.h" // Python Embedding을 위한 Header
extern "C" __declspec(dllexport) void qerogram() {
PyObject* pName, * pModule;
Py_Initialize();
pName = PyString_FromString("qerogram"); // Python Embedding할 python Source Code or pyc 파일
pModule = PyImport_Import(pName); // import qerogram
if (pModule) {
PyObject* pFunc = PyObject_GetAttrString(pModule, "hello_qerogram"); // qerogram.hello_qerogram()함수 찾기.
PyObject* pValue = PyObject_CallObject(pFunc, NULL); // qerogram.hello_qerogram(NULL) 호출
}
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
3. 사용할 C++ 소스 작성하자. DLL을 불러와서 사용해주면 된다.
// DLL Load Example
#include <stdio.h>
#include <Windows.h>
typedef void (*qerogram)();
int main() {
HMODULE hModule = LoadLibraryA("qerogram.dll");
qerogram q = (qerogram)GetProcAddress(hModule, "qerogram");
q();
return 0;
}
Conclusion
별 거 없는데, 처음에 이해가 안됐다. 그래도 익혀두면, 급할 때 교체해서 테스팅하기엔 좋은 것 같다.
실제로 활용하기에는 본문에서 사용된 함수만으로는 불편할 것이다. 따라서, 아래의 Reference에서 필요한 부분을 이용해 구현하면 된다.
'잡다한 것' 카테고리의 다른 글
Logstash grok test용 conf 파일 (0) | 2021.03.31 |
---|---|
KIBANA 설치 (0) | 2021.03.25 |
mnist dataset 로드할 때, 503 error 해결방법 (0) | 2021.03.18 |
Alfred SSH Plugin 개발 (0) | 2020.05.29 |
쉘 스크립트로 mysql 쉽게 접속하기 (0) | 2018.01.31 |
블로그의 정보
Data+
Qerogram