research:embeddedpython
차이
문서의 선택한 두 판 사이의 차이를 보여줍니다.
양쪽 이전 판이전 판다음 판 | 이전 판 | ||
research:embeddedpython [2014/01/26 19:28] – [세번째 예제] changwoo | research:embeddedpython [2014/10/09 21:24] (현재) – 바깥 편집 127.0.0.1 | ||
---|---|---|---|
줄 127: | 줄 127: | ||
=== C의 데이터를 파이썬의 객체형으로 표현 === | === C의 데이터를 파이썬의 객체형으로 표현 === | ||
- | 우선 C의 데이터를 파이썬의 객체형으로 표현하는 법에 대해 설명합니다. C에서 파이썬의 문자열을 생성하는 함수는 [[http:// | + | 우선 C의 데이터를 파이썬의 객체형으로 표현하는 법에 대해 설명합니다. C에서 파이썬의 문자열을 생성하는 함수는 [[http:// |
<code C> | <code C> | ||
char *str = NULL; | char *str = NULL; | ||
줄 148: | 줄 148: | ||
pSysModule = PyImport_Import(pModuleName); | pSysModule = PyImport_Import(pModuleName); | ||
</ | </ | ||
+ | |||
=== 파이썬의 변수/ | === 파이썬의 변수/ | ||
파이썬의 변수, 함수, 클래스는 모두 모듈의 ' | 파이썬의 변수, 함수, 클래스는 모두 모듈의 ' | ||
줄 176: | 줄 177: | ||
PyObject *pArgList; | PyObject *pArgList; | ||
- | pSampleClass = PyObject_GetAttrString(" | + | pSampleClass = PyObject_GetAttrString(pSampleClass, " |
pArgList = Py_BuildValue(" | pArgList = Py_BuildValue(" | ||
pInstance = PyObject_CallObject(pSampleClass, | pInstance = PyObject_CallObject(pSampleClass, | ||
줄 195: | 줄 196: | ||
pComplexReturn = PyComplex_AsCComplex(pyComplexObject); | pComplexReturn = PyComplex_AsCComplex(pyComplexObject); | ||
</ | </ | ||
+ | |||
+ | 리스트나 딕셔너리에서 값을 가져올 때는 '' | ||
=== 레퍼런스 카운팅 === | === 레퍼런스 카운팅 === | ||
줄 200: | 줄 203: | ||
한편 [[http:// | 한편 [[http:// | ||
+ | |||
+ | |||
=== 두번째 예제 코드 === | === 두번째 예제 코드 === | ||
이제 소스 코드를 볼께요. 간단한 함수 호출 하나를 하는데 좀 많이 난리를 쳐야 합니다. | 이제 소스 코드를 볼께요. 간단한 함수 호출 하나를 하는데 좀 많이 난리를 쳐야 합니다. | ||
줄 264: | 줄 269: | ||
==== 세번째 예제 ==== | ==== 세번째 예제 ==== | ||
- | 세번째 예제는 조금 더 다양하게 가 보도록 하죠. urllib을 이용해 웹페이지의 소스 코드를 가져와, 외부 링크 즉, '' | + | 세번째 예제는 조금 더 다양하게 가 보도록 하죠. urllib을 이용해 웹페이지의 소스 코드를 가져와, 외부 링크 즉, '' |
- | ===== boost::python | + | < |
+ | # | ||
+ | import urllib | ||
+ | import re | ||
+ | href_expr = re.compile(r'< | ||
+ | |||
+ | class count_href(object): | ||
+ | def __init__(self): | ||
+ | self.results = [] | ||
+ | |||
+ | def count(self, url): | ||
+ | html = self.get_html(url) | ||
+ | found = href_expr.findall(html) | ||
+ | d = {" | ||
+ | for item in found: | ||
+ | d[" | ||
+ | self.results.append(d) | ||
+ | |||
+ | def get_html(self, | ||
+ | opened = urllib.urlopen(url) | ||
+ | html = opened.read() | ||
+ | opened.close() | ||
+ | return html | ||
+ | |||
+ | def get_result(self): | ||
+ | return self.results | ||
+ | </ | ||
+ | |||
+ | 이 모듈은 이렇게 사용하겠죠. | ||
+ | <code python> | ||
+ | import count_href | ||
+ | |||
+ | if __name__ == ' | ||
+ | counter = count_href.count_href() | ||
+ | counter.count(' | ||
+ | counter.count(' | ||
+ | counter.count(' | ||
+ | |||
+ | result = counter.get_result() | ||
+ | for item in result: | ||
+ | print "URL: " + item[" | ||
+ | print len(item[" | ||
+ | #for link in item[" | ||
+ | # print link | ||
+ | </ | ||
+ | |||
+ | 이 모듈의 클래스를 C 코드에서 가져오도록 합니다. | ||
+ | <code C count_href.c> | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | void extract(PyObject* instance) | ||
+ | { | ||
+ | PyObject *returned_object; | ||
+ | Py_ssize_t i, list_size; | ||
+ | |||
+ | returned_object = PyObject_CallMethod(instance, | ||
+ | |||
+ | /* returned_object: | ||
+ | every dict has keys: url, links | ||
+ | links is also list */ | ||
+ | list_size = PyList_Size(returned_object); | ||
+ | |||
+ | for(i = 0; i < list_size; ++i) { | ||
+ | |||
+ | PyObject *dict_item, *url, *links; | ||
+ | Py_ssize_t links_size, j; | ||
+ | |||
+ | dict_item = PyList_GetItem(returned_object, | ||
+ | assert(dict_item != NULL); | ||
+ | |||
+ | url = PyDict_GetItemString(dict_item, | ||
+ | assert(url != NULL); | ||
+ | |||
+ | links = PyDict_GetItemString(dict_item, | ||
+ | assert(links != NULL); | ||
+ | |||
+ | links_size = PyList_Size(links); | ||
+ | printf(" | ||
+ | printf(" | ||
+ | |||
+ | for(j = 0; j < links_size; ++j) { | ||
+ | |||
+ | PyObject *entry_item = PyList_GetItem(links, | ||
+ | |||
+ | assert(entry_item != NULL); | ||
+ | printf(" | ||
+ | } | ||
+ | |||
+ | Py_DECREF(returned_object); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | int main(int argc, char** argv) | ||
+ | { | ||
+ | int i; | ||
+ | PyObject *module, *class, *instance; | ||
+ | int size; | ||
+ | |||
+ | if(argc < 2) { | ||
+ | fprintf(stderr, | ||
+ | return 1; | ||
+ | } | ||
+ | |||
+ | Py_Initialize(); | ||
+ | PyRun_SimpleString( | ||
+ | " | ||
+ | " | ||
+ | |||
+ | module = PyImport_ImportModule(" | ||
+ | assert(module != NULL); | ||
+ | |||
+ | class = PyObject_GetAttrString(module, | ||
+ | assert(class != NULL); | ||
+ | |||
+ | instance = PyObject_CallObject(class, | ||
+ | assert(instance != NULL); | ||
+ | |||
+ | for(i = 1; i < argc; ++i) { | ||
+ | printf(" | ||
+ | PyObject_CallMethod(instance, | ||
+ | } | ||
+ | |||
+ | extract(instance); | ||
+ | Py_Finalize(); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== 정리 ==== | ||
+ | * 프로그램 시작: Py_SetProgramName(선택적), | ||
+ | * 모듈 불러오기 | ||
+ | * PyImport_Import: | ||
+ | * PyImport_ImportModule: | ||
+ | * 주의! 모듈 경로에 현재 디렉토리가 포함되지 않음. | ||
+ | * 해결책 | ||
+ | - setenv(" | ||
+ | - PyRun_SimpleString(" | ||
+ | * 모듈에서 객체(클래스, | ||
+ | * PyObject_GetAttrString | ||
+ | * 호출 가능한(callable) 객체 부르기 | ||
+ | * PyObject_Call: | ||
+ | * PyObject_CallObject: | ||
+ | * PyObject_CallFunction: | ||
+ | * PyObject_CallMethod: | ||
+ | * PyObject_CallFunctionObjArgs: | ||
+ | * PyObject_CallMethodObjArgs: | ||
+ | * 값 가져오기 | ||
+ | * Int, Long, Float, Complex, String: Py[python_type]_As[c_type] | ||
+ | * Dictionary, List: PyDict_GetItem, | ||
+ | * 값 설정하기 | ||
+ | * Int, Long, Float, Complex, String: Py[python_type]_From[c_type] | ||
+ | * Dictionary, List: PyDict_SetItem, | ||
+ | * 레퍼런스 설정하기 | ||
+ | * Py_INCREF, Py_DECREF: 레퍼런스 카운트 증가, 감소 | ||
+ | * Py_CLEAR: 레퍼런스 카운트를 없앰 | ||
+ | * 프로그램 종료: Py_Finalize | ||
+ | |||
+ | |||
+ | |||
+ | |||
+ | ===== boost.python 사용하기 ===== | ||
+ | C API를 활용하여 원하는 기능을 구현할 수도 있지만, 간단한 데이터를 가져오는데도 상당히 코드가 많이 필요합니다. API를 간단히 파악하는 정도로 두고, 보다 간결하고 편리하게 쓸 수 있는 라이브러리를 찾아야 할 것 같습니다. | ||
+ | |||
+ | [[https:// | ||
+ | |||
+ | <code make Makefile> | ||
+ | CC = / | ||
+ | PYTHON_CONFIG = / | ||
+ | |||
+ | BOOST_INC_PATH = / | ||
+ | BOOST_LIB_PATH = / | ||
+ | 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: | ||
+ | SRC = $(TAR: | ||
+ | |||
+ | all: $(TAR) | ||
+ | .o.out: $(OBJ) | ||
+ | $(CC) $(LDFLAGS) | ||
+ | |||
+ | .cpp.o: %.cpp | ||
+ | $(CC) $(CFLAGS) | ||
+ | |||
+ | clean: | ||
+ | rm -rf $(TAR) $(OBJ) | ||
+ | </ | ||
+ | |||
+ | ==== 첫번째 boost.python 예제 ==== | ||
+ | <code cpp hello_py.cpp> | ||
+ | #include < | ||
+ | |||
+ | int main(int argc, char** argv) | ||
+ | { | ||
+ | Py_Initialize(); | ||
+ | boost:: | ||
+ | Py_Finalize(); | ||
+ | return 0; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | 현재는 별다른 것이 없어 보이네요 | ||
+ | |||
+ | ==== 두번째 boost.python 예제 ==== | ||
+ | |||
+ | <code cpp call.cpp> | ||
+ | #include < | ||
+ | #include < | ||
+ | |||
+ | namespace bp = boost:: | ||
+ | |||
+ | void workaround_for_local_modules() | ||
+ | { | ||
+ | PyRun_SimpleString( | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | |||
+ | int main(int argc, char** argv) | ||
+ | { | ||
+ | if (argc < 3) { | ||
+ | fprintf(stderr," | ||
+ | return 1; | ||
+ | } | ||
+ | |||
+ | Py_Initialize(); | ||
+ | workaround_for_local_modules(); | ||
+ | |||
+ | try { | ||
+ | bp:: | ||
+ | bp:: | ||
+ | bp:: | ||
+ | |||
+ | module_name = bp:: | ||
+ | module = bp:: | ||
+ | func = module.attr(argv[2]); | ||
+ | |||
+ | if(func && PyCallable_Check(func.ptr())) { | ||
+ | bp:: | ||
+ | |||
+ | tuple = bp:: | ||
+ | for(int i = 0; i < argc - 3; ++i) { | ||
+ | PyObject* arg; | ||
+ | arg = PyInt_FromLong(atoi(argv[i+3])); | ||
+ | PyTuple_SetItem(tuple.ptr(), | ||
+ | } | ||
+ | |||
+ | bp:: | ||
+ | int value; | ||
+ | |||
+ | valueObj = bp:: | ||
+ | value = bp:: | ||
+ | |||
+ | std:: | ||
+ | } | ||
+ | |||
+ | } catch(bp:: | ||
+ | PyErr_Print(); | ||
+ | } | ||
+ | |||
+ | Py_Finalize(); | ||
+ | return EXIT_SUCCESS; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | '' | ||
+ | |||
+ | |||
+ | ==== 세번째 boost.python 예제 ==== | ||
+ | <code cpp count_href.cpp> | ||
+ | |||
+ | </ | ||
===== 참고 사이트 ===== | ===== 참고 사이트 ===== | ||
* [[http:// | * [[http:// | ||
+ | * [[https:// | ||
+ | * [[http:// |
research/embeddedpython.1390764537.txt.gz · 마지막으로 수정됨: 2014/10/09 21:23 (바깥 편집)