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에서 필요한 부분을 이용해 구현하면 된다.
블로그의 정보
Data+
Qerogram