파이썬을 사용해보자!
안녕하세요. Teemol입니다.
오늘은 C++에서 Python을 사용하는 방법입니다.
먼저 아래의 링크에서 Python을 설치해야 합니다.
Downloads 탭에서 원하는 버전 / 플랫폼의 Installer를 받아서 설치합니다.
저는 Python 3.7.7 / Window x86 executable installer를 다운로드해서 진행하도록 하겠습니다.
설치 시 Customize installation에서 Download debug binaries를 체크하고 진행합니다.
*이 설정으로 디버그에서 사용하는 라이브러리를 받을 수 있습니다.
파이썬의 기본 설치 경로는 아래와 같습니다.
C:\Users\{User}\AppData\Local\Programs\Python
저는 아래와 같은 경로에 설치되었습니다.
C:\Users\Administrator\AppData\Local\Programs\Python\Python37-32
경로를 확인하는 이유는 헤더와 라이브러리를 가져오기 위해서입니다.
Python을 사용할 C++ 프로젝트에서 위의 경로에 있는 include 폴더와 libs 폴더를 각각 포함 디렉터리와 라이브러리 디렉터리에 추가합니다.
ex)
포함 디렉터리 > C:\Users\Administrator\AppData\Local\Programs\Python\Python37-32\include
라이브러리 디렉터리 > C:\Users\Administrator\AppData\Local\Programs\Python\Python37-32\libs
그리고 링커 > 입력 > 추가 종속성에 python37.lib를 추가합니다.
*버전에 따라 .lib 명이 다를 수 있습니다.
이제 프로젝트에 python37.dll과 python37_d.dll을 추가합니다.
*버전에 따라 .dll 명이 다를 수 있습니다.
이제 Python을 사용할 수 있습니다.
Python을 사용 시 아래의 내용을 추가하고 사용해야 합니다.
그렇지 않으면 Debug에서 제대로 동작하지 않을 수 있습니다.
#define HAVE_ROUND
#ifdef _DEBUG
#define RESTORE_DEBUG
#undef _DEBUG
#endif
#include <Python.h>
#ifdef RESTORE_DEBUG
#define _DEBUG
#undef RESTORE_DEBUG
#endif
간단한 예제를 만들어 보겠습니다.
예제 1. 아래의 코드는 C++에서 Python의 함수를 호출하는 내용입니다.
CPP CODE
PyObject* module_name, * module, * pFunc;
Py_Initialize();
module_name = PyUnicode_FromString("Sample");
module = PyImport_Import(module_name);
if (module == nullptr) {
PyErr_Print();
std::cerr << "Fails to import the module.\n";
return 1;
}
Py_DECREF(module_name);
pFunc = PyObject_GetAttrString(module, "Function");
Py_DECREF(module);
PyObject_CallObject(pFunc, nullptr);
Py_DECREF(pFunc);
Py_Finalize();
PYTHON CODE (Sample.py)
def Function():
print("Hello Python!")
예제 2. 아래의 코드는 C++에서 Python의 Sample 클래스 안에 있는 함수인 두 개의 숫자를 받고 두 값을 더해서 돌려주는 함수를 호출하는 내용입니다.
CPP CODE
PyObject* module_name, * module, * dict, * python_class, * object, * args, * func;
Py_Initialize();
module_name = PyUnicode_FromString("Sample2");
module = PyImport_Import(module_name);
if (module == nullptr) {
PyErr_Print();
return 1;
}
Py_DECREF(module_name);
dict = PyModule_GetDict(module);
if (dict == nullptr) {
PyErr_Print();
return 1;
}
Py_DECREF(module);
python_class = PyDict_GetItemString(dict, "Sample");
if (python_class == nullptr) {
PyErr_Print();
return 1;
}
Py_DECREF(dict);
if (PyCallable_Check(python_class)) {
object = PyObject_CallObject(python_class, nullptr);
Py_DECREF(python_class);
}
else {
Py_DECREF(python_class);
return 1;
}
func = PyObject_GetAttrString(object, "Sum");
Py_DECREF(object);
args = PyTuple_New(2);
PyTuple_SetItem(args, 0, PyLong_FromLong(1));
PyTuple_SetItem(args, 1, PyLong_FromLong(2));
PyObject* value = PyObject_CallObject(func, args);
Py_DECREF(args);
Py_DECREF(func);
long result = PyLong_AsLong(value);
Py_DECREF(value);
Py_Finalize();
PYTHON CODE (Sample2.py)
class Sample:
def Sum(self, num1, num2):
return ( num1 + num2 )
함수의 첫 번째 인자 self는 아래와 같은 방식으로 사용하지 않을 수 있습니다.
class Sample:
@staticmethod
def Sum(num1, num2):
return ( num1 + num2 )
마지막으로 Python을 포함해서 배포하는 방법입니다.
Python Installer를 받은 곳에서 embeddable zip file을 다운로드합니다.
ex) Windows x86 embeddable zip file
해당 파일을 받아서 압축을 풀면 또 하나의 .zip 파일이 있습니다.
저는 python37.zip 파일이 있습니다.
*버전에 따라 .zip 명이 다를 수 있습니다.
python37.zip 파일을 배포할 응용프로그램이 있는 폴더로 이동 후 Python을 사용하는 코드의 시작 부분에 아래의 내용을 추가합니다.
//ADD
Py_SetPythonHome(L"python37");
Py_Initialize();
module_name = PyUnicode_FromString("Sample2");
SetPythonHome(L"python37")을 추가하였습니다.
위 내용을 추가하고 빌드 한 뒤 응용프로그램을 배포할 때 python37.zip을 같이 배포하면 Python이 설치되어 있지 않아도 Python을 사용할 수 있습니다.
*주의사항
Python 파일명이 Lib에 있는 파일명과 동일하면 Lib의 내용을 먼저 읽어서 제대로 동작하지 않습니다.
ex) test.py, abc.py 등
- 끄읕