Python C API

C, C++ 2018. 11. 21. 15:52 |
반응형

가장 간단하게 Python을 C에 embed 시키는 방법은 Very High Level interface를 사용하는 것이다. VHL interface는 어플리케이션과 직접적인 상관없이 Python script를 실행하기 위한 것이다. Python을 설치했다면 따로 설치할 프로그램은 없다.

 

관련 문서

Python/C API Reference Manual

 

우선 Python C API 관련 Include, Library 디렉토리를 프로젝트에 추가한다.

C:\Users\UserName\AppData\Local\Programs\Python\PythonXXX\include

C:\Users\UserName\AppData\Local\Programs\Python\PythonXXX\libs

 

 

파이썬 공식 홈페이지에서 다운받은 파이썬 인스톨러 패키지를 설치했다면 Solution Configurations를 Release로 설정한다. Debug 모드로 build할 경우 pythonXX_d.lib를 찾을 수 없다는 에러가 발생한다. pythonXX_d.lib 파일을 생성하려면 파이썬 소스를 받아서 직접 컴파일해야 한다.

 

예제:

 

#pragma comment(lib, "python36.lib")
#include <Python.h>

int main(int argc, char *argv[])
{
    wchar_t *program = Py_DecodeLocale(argv[0], NULL);
    // Decode a byte string from the locale encoding with the surrogateescape error handler:
    // undecodable bytes are decoded as characters in range U+DC80..U+DCFF. If a byte sequence
    // can be decoded as a surrogate character, escape the bytes using the surrogateescape error
    // handler instead of decoding them.
    // Return a pointer to a newly allocated wide character string, use PyMem_RawFree() to free
    // the memory. If size is not NULL, write the number of wide characters excluding the null
    // character into *size
    if (program == NULL) {
        fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
        exit(1);
    }
    Py_SetProgramName(program);  /* optional but recommended */
    // This function should be called before Py_Initialize() is called for the first time, if it
    // is called at all.It tells the interpreter the value of the argv[0] argument to the main()
    // function of the program(converted to wide characters).This is used by Py_GetPath() and some
    // other functions below to find the Python run - time libraries relative to the interpreter
    // executable.

    Py_Initialize();
    // Initialize the Python interpreter. In an application embedding Python, this should be called
    // before using any other Python/C API functions
    if (Py_IsInitialized())
    // Return true (nonzero) when the Python interpreter has been initialized, false (zero) if not.
    // After Py_FinalizeEx() is called, this returns false until Py_Initialize() is called again.
    {
        PyRun_SimpleString("print('Hello Python')");
        // This is a simplified interface to PyRun_SimpleStringFlags(), leaving the PyCompilerFlags*
        // argument set to NULL.
        PyRun_SimpleString("from time import time, ctime\n"
            "print('Today is', ctime(time()))\n");
        //PyRun_SimpleString("from time import time, ctime\nprint('Today is', ctime(time()))\n");

        if (Py_FinalizeEx() < 0)
        // Undo all initializations made by Py_Initialize() and subsequent use of Python/C API
        // functions, and destroy all sub-interpreters that were created and not yet destroyed
        // since the last call to Py_Initialize().
        {
            exit(120);
        }
        PyMem_RawFree(program);
        // Frees the memory block pointed to by p, which must have been returned by a previous call
        // to PyMem_RawMalloc(), PyMem_RawRealloc() or PyMem_RawCalloc().
        // Otherwise, or if PyMem_RawFree(p) has been called before, undefined behavior occurs.
        // If p is NULL, no operation is performed.
    }

    return 0;
}

 

 

간단히 파이썬 스크립트만 실행시키고 싶다면 아래와 같이 해도 된다.

 

<test.py>

print("Testing...")

 

<source.cpp>

#include <iostream>

int main() {
	std::string script = "test.py";	
	std::string command = "python " + script;
	//std::string command = "C:/Users/Sean/AppData/Local/Programs/Python/PythonXXX/python.exe " + script;
	// 빌드된 파일을 실행할땐 상관 없지만 Ctrl+F5로 실행할땐 python.exe의 전체 경로를 다 적어야 한다.

	int result = std::system(command.c_str());
	if (result != 0) {
		std::cerr << "Python script failed: " << result << std::endl;
	}

	return 0;
}

 

 

반응형
Posted by J-sean
: