사용자 도구

사이트 도구


research:embeddedpython

차이

문서의 선택한 두 판 사이의 차이를 보여줍니다.

차이 보기로 링크

양쪽 이전 판이전 판
다음 판
이전 판
research:embeddedpython [2014/01/26 22:40] – [세번째 예제] changwooresearch:embeddedpython [2014/10/09 21:24] (현재) – 바깥 편집 127.0.0.1
줄 127: 줄 127:
  
 === C의 데이터를 파이썬의 객체형으로 표현 === === C의 데이터를 파이썬의 객체형으로 표현 ===
-우선 C의 데이터를 파이썬의 객체형으로 표현하는 법에 대해 설명합니다. C에서 파이썬의 문자열을 생성하는 함수는 [[http://docs.python.org/2/c-api/string.html#PyString_FromString|PyString_FromString()]]입니다. 리턴 형은 ''PyObject*''인데 모든 파이썬의 데이터는 이 ''PyObject''입니다. 파이썬의 어떤 자료형이라도 PyObject로 표현되므로, 항상 주의하여야 합니다.+우선 C의 데이터를 파이썬의 객체형으로 표현하는 법에 대해 설명합니다. C에서 파이썬의 문자열을 생성하는 함수는 [[http://docs.python.org/2/c-api/string.html#PyString_FromString|PyString_FromString()]]입니다. 리턴 형은 ''PyObject*''인데 모든 파이썬의 데이터는 이 ''PyObject''입니다. 파이썬의 어떤 자료형이라도 ''PyObject''로 표현되므로, 항상 주의하여야 합니다.
 <code C> <code C>
   char *str = NULL;   char *str = NULL;
줄 401: 줄 401:
 } }
 </code> </code>
-===== boost python 사용하기 ===== 
  
 +==== 정리 ====
 +  * 프로그램 시작: Py_SetProgramName(선택적), Py_Initialize
 +  * 모듈 불러오기
 +    * PyImport_Import: PyObject* 를 사용
 +    * PyImport_ImportModule: char* 를 사용
 +    * 주의! 모듈 경로에 현재 디렉토리가 포함되지 않음.
 +      * 해결책
 +        - setenv("PYTHONPATH", ".", 1)
 +        - PyRun_SimpleString("import sys\n" "sys.path.append('.')\n");
 +  * 모듈에서 객체(클래스, 함수) 불러오기
 +    * PyObject_GetAttrString
 +  * 호출 가능한(callable) 객체 부르기
 +    * PyObject_Call: callable에 tuple arg, dictionary kw 인자를 넘김
 +    * PyObject_CallObject: tuple args 인자를 넘김
 +    * PyObject_CallFunction: C fomat을 사용하여 호출
 +    * PyObject_CallMethod: object의 method를 호출
 +    * PyObject_CallFunctionObjArgs: CallFunction과 동일하나 PyObject*를 인자로 넘김
 +    * PyObject_CallMethodObjArgs: CallMethod와 동일하나 PyObject*를 인자로 넘김
 +  * 값 가져오기
 +    * Int, Long, Float, Complex, String: Py[python_type]_As[c_type]
 +    * Dictionary, List: PyDict_GetItem, PyList_GetItem
 +  * 값 설정하기
 +    * Int, Long, Float, Complex, String: Py[python_type]_From[c_type]
 +    * Dictionary, List: PyDict_SetItem, PyList_SetItem
 +  * 레퍼런스 설정하기
 +    * Py_INCREF, Py_DECREF: 레퍼런스 카운트 증가, 감소
 +    * Py_CLEAR: 레퍼런스 카운트를 없앰
 +  * 프로그램 종료: Py_Finalize
 +
 +
 +
 +
 +===== boost.python 사용하기 =====
 +C API를 활용하여 원하는 기능을 구현할 수도 있지만, 간단한 데이터를 가져오는데도 상당히 코드가 많이 필요합니다. API를 간단히 파악하는 정도로 두고, 보다 간결하고 편리하게 쓸 수 있는 라이브러리를 찾아야 할 것 같습니다. 
 +
 +[[https://wiki.python.org/moin/IntegratingPythonWithOtherLanguages | 파이썬 위키]]에 다른 언어와 파이썬을 연동하는 방법이 잘 나와 있습니다. 여기서는 C++의 대표적인 라이브러리인 [[http://www.boost.org/| Boost C++ Libraries]]를 사용하도록 하겠습니다.
 +
 +<code make Makefile>
 +CC = /usr/bin/g++
 +PYTHON_CONFIG = /opt/local/bin/python2.7-config
 +
 +BOOST_INC_PATH = /opt/local/include
 +BOOST_LIB_PATH = /opt/local/lib
 +CFLAGS = `$(PYTHON_CONFIG) --cflags` -I $(BOOST_INC_PATH)
 +LDFLAGS = `$(PYTHON_CONFIG) --ldflags` -L $(BOOST_LIB_PATH) -lboost_python-mt
 +
 +TAR = test.out hello_py.out # 여기에 .out 파일을 추가하세요
 +OBJ = $(TAR:.out=.o)
 +SRC = $(TAR:.out=.cpp)
 + 
 +all: $(TAR)
 +.o.out: $(OBJ)
 + $(CC) $(LDFLAGS)  -o $@ $<
 + 
 +.cpp.o: %.cpp
 + $(CC) $(CFLAGS)  -c $<
 + 
 +clean:
 + rm -rf $(TAR) $(OBJ)
 +</code>
 +
 +==== 첫번째 boost.python 예제 ====
 +<code cpp hello_py.cpp>
 +#include <boost/python/exec.hpp>
 +
 +int main(int argc, char** argv)
 +{
 + Py_Initialize();
 + boost::python::exec("print \'Hello, World!\'\n");
 + Py_Finalize();
 + return 0;
 +}
 +</code>
 +
 +현재는 별다른 것이 없어 보이네요
 +
 +==== 두번째 boost.python 예제 ====
 +
 +<code cpp call.cpp>
 +#include <iostream>
 +#include <boost/python.hpp>
 +
 +namespace bp = boost::python;
 +
 +void workaround_for_local_modules()
 +{
 + PyRun_SimpleString(
 + "import sys\n"
 + "sys.path.append('.')\n");
 +}
 +
 +int main(int argc, char** argv)
 +{
 +    if (argc < 3) {
 +        fprintf(stderr,"Usage: call pythonfile funcname [args]\n");
 +        return 1;
 +    }
 +
 + Py_Initialize();
 + workaround_for_local_modules();
 +
 + try {
 + bp::object module_name;
 + bp::object module;
 + bp::object func;
 +
 + module_name = bp::object(bp::handle<>(PyString_FromString(argv[1])));
 + module = bp::object(bp::handle<>(PyImport_Import(module_name.ptr())));
 + func = module.attr(argv[2]);
 +
 + if(func && PyCallable_Check(func.ptr())) {
 + bp::object tuple;
 +
 + tuple = bp::object(bp::handle<>(PyTuple_New(argc - 3)));
 + for(int i = 0; i < argc - 3; ++i) {
 + PyObject* arg;
 + arg = PyInt_FromLong(atoi(argv[i+3]));
 + PyTuple_SetItem(tuple.ptr(), i, arg);
 + }
 +
 + bp::object valueObj;
 + int value;
 +
 + valueObj = bp::object(bp::handle<>(PyObject_CallObject(func.ptr(), tuple.ptr())));
 + value = bp::extract<int>(valueObj);
 +
 + std::cout << value << std::endl;
 + }
 +
 + } catch(bp::error_already_set const &) {
 + PyErr_Print();
 + }
 +
 + Py_Finalize();
 + return EXIT_SUCCESS;
 +}
 +</code>
 +
 +''PyObject''가 ''boost::python::object''로 래핑되어 있습니다. 또한 ''boost::python::handle<>''을 이용하면 ''PyObject''의 레퍼런스를 관리해 줍니다. ''boost::python''의 대부분의 기능은 extending에 초점이 맞춰져 있고 embedding에는 그다지 많은 기능을 제공하지 않는 편이므로 상당히 많은 부분에서 C API를 그대로 가져와 사용해야 합니다.
 +
 +
 +==== 세번째 boost.python 예제 ====
 +<code cpp count_href.cpp>
 +
 +</code>
 ===== 참고 사이트 ===== ===== 참고 사이트 =====
   * [[http://docs.python.org/2/extending/embedding.html|Embedding Python in Another Application]]   * [[http://docs.python.org/2/extending/embedding.html|Embedding Python in Another Application]]
 +  * [[https://wiki.python.org/moin/IntegratingPythonWithOtherLanguages | Integrating Python With Other Languages]]
 +  * [[http://www.boost.org/doc/libs/1_55_0/libs/python/doc/index.html | Boost.Python Index]]
research/embeddedpython.1390776011.txt.gz · 마지막으로 수정됨: 2014/10/09 21:23 (바깥 편집)

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki