웹프로그래밍
Pytthon embeddeding : 파이썬을 c언어에 내장하기 작업일지 2 - 인터렉티브 본문
'Pytthon embeddeding : 파이썬을 c언어에 내장하기 작업일지 1 - 모듈사용' 에 이어 이번에는 C,C++에서 직접 파이썬 모듈을 로드하여 전달인자와 함께 호출하고 리턴값을 받아오는 과정을 진행합니다.
이번에도 마찬가지로 제가 겪는 시행 착오와 이를 풀어가는 과정을 기록하겠습니다.
컴파일 옵션궁금하다면 이전 게시물을 참고하면 됩니다.
다음의 사이트에 소스 및 자세한 설명이 있으며 여기에서는 해당 사이트만 참고해서는 제대로 동작하지 않는 부분을 해결하는 과정만을 다룹니다.
http://docs.python.org/extending/embedding.html
1. C에서 파이선모듈을 전달인자와 함께 호출하여 리턴값을 받는 과정에 대해 열심히 공부한다음, 코드들을 각각 main.c multiple.py 로 저장하고 다음 명령으로 컴파일하면 무사히 컴파일 된다.
$ g++ main.cpp -I/usr/include/python2.6 -pthread -lm -ldl -lutil /usr/lib/libpython2.6.so
2. 하지만 다음의 전달인자들로 프로그램을 실행하면 원하는 결과를 얻을 수 없다.
$ ./a.out multiply multiply 3 2 ImportError: No module named multiply Failed to load "multiply" |
이전과 마찬가지로 파이썬 스크립트를 실행파일과 같은 디렉터리에 두었지만 모듈을 로드하지 못하였다.
3. 그래서 이전과 마찬가지로 main.cpp 에 다음 코드를 추가한다.
PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.path"); PyRun_SimpleString("sys.path.append('/root/work/Twitter/Python/embedding_test3')"); |
파란 부분은 작업 디렉터리의 위치 즉 로드할 모듈의 위치이다.
4. 컴파일해서 실행하면 원하는 결과를 얻을 수 있다.
# ./a.out multiply multiply 3 2 Will compute 3 times 2 Result of call: 6 |
모듈의 위치를 추가하는 부분에 대해 언급이 없는 이유는 잘 모르겠다. 무언가 보다 근본적인 해결 방법이 있을 것 같은데...
소스분석
...생략 Py_Initialize(); pName = PyString_FromString(argv[1]); //로드할 모듈의 이름을을 받아와서 /* Error checking of pName left out */ pModule = PyImport_Import(pName); // 모듈을 로드 Py_DECREF(pName); // 참조횟수를 감소시킴 파이썬은 c언어처럼 malloc(), free(), 등으로 메모리를 관리하지 않고 레퍼런스카운터를 통해 메모리를 관리함. 카운터가 0이 되면 메모리가 해제됨. 자세한 사항은 다음을 참고 http://docs.python.org/extending/extending.html#refcounts // 프로그램을 다음과 같은 인자로 실행했다고 할 때 $ ./a.out multiply multiply 3 2 if (pModule != NULL) { pFunc = PyObject_GetAttrString(pModule, argv[2]); // 모듈에서 호출하려고 하는 함수의 레퍼런스를 pFunc 에 받아온다. /* pFunc is a new reference */ if (pFunc && PyCallable_Check(pFunc)) { // 해당 함수가 호출 가능한지 검사한다. pArgs = PyTuple_New(argc - 3); // pArgs 에 5-3 갯수의 튜플을 생성한다 for (i = 0; i < argc - 3; ++i) { pValue = PyInt_FromLong(atoi(argv[i + 3])); // 3 과 2 를 차례로 pValue에 저장하여 if (!pValue) { // 매계변수를 제대로 입력하지 않았다면 에러처리를 한다 Py_DECREF(pArgs); Py_DECREF(pModule); fprintf(stderr, "Cannot convert argument\n"); return 1; } /* pValue reference stolen here: */ PyTuple_SetItem(pArgs, i, pValue); // 이상이 없다면 pArgs 의 튜플에 3 과 2 를 저장한다. } pValue = PyObject_CallObject(pFunc, pArgs); // multi 함수에 전달인자를 주어 호출하고 리턴값을 pValue에 받아온다 Py_DECREF(pArgs); if (pValue != NULL) { printf("Result of call: %ld\n", PyInt_AsLong(pValue)); // 리턴값을 출력한다. PyInt_AsLong 은 파이썬자료형을 long형으로 리턴한다 Py_DECREF(pValue); } else { Py_DECREF(pFunc); Py_DECREF(pModule); PyErr_Print(); fprintf(stderr,"Call failed\n"); return 1; } } else { if (PyErr_Occurred()) PyErr_Print(); fprintf(stderr, "Cannot find function \"%s\"\n", argv[2]); } Py_XDECREF(pFunc); Py_DECREF(pModule); } else { PyErr_Print(); fprintf(stderr, "Failed to load \"%s\"\n", argv[1]); return 1; } 생략... |
__
'프로그래밍일반' 카테고리의 다른 글
IA Register Set (0) | 2016.07.13 |
---|---|
STB 스터디 자료 (0) | 2016.07.13 |
Pytthon embeddeding : 파이썬을 c언어에 내장하기 작업일지 1 - 모듈사용 (0) | 2016.07.13 |
Python 을 eclipse 에서 개발, 디버깅하기 (0) | 2016.07.13 |
트위터 API를 타겟보드에 포팅하기(Porting Twitter API on a Target Board) (0) | 2016.07.13 |