Data+

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에서 필요한 부분을 이용해 구현하면 된다.

[+] https://docs.python.org/ko/3/extending/embedding.html

블로그의 프로필 사진

블로그의 정보

Data+

Qerogram

활동하기