Notice
Recent Posts
Recent Comments
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

웹프로그래밍

Pytthon embeddeding : 파이썬을 c언어에 내장하기 작업일지 1 - 모듈사용 본문

프로그래밍일반

Pytthon embeddeding : 파이썬을 c언어에 내장하기 작업일지 1 - 모듈사용

공부모드 2016. 7. 13. 05:07

파이썬 모듈을 C, C++ 에서 호출하는 과정에서 겪은 시행착오를 기록 하였으며 마지막 부분에서는 실제 동작하는 코드와 컴파일 방법을 제시합니다.


작업환경
파이썬 : 2.6.5
운영체제 : Linux Fedora 12
커널 : 2.6.32
gcc : 4.3.3

  • 파이썬에대한 문법적, 개념적 지식이 없더라도 소스를 보시면 쉽게 이해할 수 있을거라 생각합니다.
  • 컴파일 옵션중 라이브러리 관련 부분은 자신의 경로에 맞게 수정해야 합니다.
  • 결과부터 보고싶다면 9번섹션만 보아도 무방하며 링크 오류 발생시에는 1번부터 따라가며 자신에 맞는 컴파일 옵셙을 찾아내야 합니다.



다음 코드는 국내 블로거 한분이 파이썬의 내장함수를 C언어에서 사용하는 방법을 제시한 것이며 이 코드로 부터 시작합니다.


#include <stdio.h>
#include <Python.h>
int main(int argc, char * argv[])
{

// initialize the interpreter
  Py_Initialize();
  // evaluate some code
  PyRun_SimpleString("import sys\n");
  //ignore line wrap on following line
  PyRun_SimpleString("sys.stdout.write('Hello from an embedded Python Script\n')\n");
  // shut down the interpreter
  Py_Finalize();
  return 0;
}
PyRun_SimpleString() 함수를 통해 파이썬 커맨드라인에 입력할 명령어를 전달인자로 전달하는 간단한 프로그램입니다.


1.위의 코드를 컴파일시 링크에러발생

라이브러리 관련 문제로 다음 명령으로 컴파일할 수 있었음
g++ x.cpp -o x -I/usr/include/python2.6 -pthread -lm -ldl -lutil /usr/lib/python2.2/config/libpython2.2.a

3. 컴파일은 잘 되지만 실행할때 다음과 같은 에러 발생
Fatal Python error: Interpreter not initialized (version mismatch?)

"Debug 버젼의 파이썬 라이브러리를 사용하고, 일반(non-debug) Python 인터프리터를 사용하거나그 반대의 경우에 나오는 메시지라고 합니다."

5. 다음 내용을 바탕으로
 
I discovered what libraries to link to by asking distutils:
import distutils.sysconfig
distutils.sysconfig.get_config_var('LIBS')
distutils.sysconfig.get_config_var('SYSLIBS')
출처 : http://www.velocityreviews.com/forums/t343059-embedding-python.html

다음을 실행하여
 [root@localhost Python]# python
Python 2.6.2 (r262:71600, Jan 25 2010, 18:46:45) 
[GCC 4.4.2 20091222 (Red Hat 4.4.2-20)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import distutils.sysconfig
>>> distutils.sysconfig.get_config_var('LIBS')
'-lpthread -ldl  -lutil'
>>> distutils.sysconfig.get_config_var('SYSLIBS')
'-lm'

파이썬을 컴파일 할 때 -lpthread -ldl -lutil -lm 옵션들을 주여야 한다고 판단하였으며... 이에대한 근거는 이 옵션들을 주었을 때에는 컴파일이 제대로 되고 그렇지 않을 경우 컴파일이 되지 않는다는 것이다. ;;

6. 또한 다음을 바탕으로
 
ldconfig -p|grep "python" 
libpython2.6.so.1.0 (libc6) => /usr/lib/libpython2.6.so.1.0
libpython2.6.so (libc6) => /usr/lib/libpython2.6.so
libpyglib-2.0-python.so.0 (libc6) => /usr/lib/libpyglib-2.0-python.so.0
libpyglib-2.0-python.so (libc6) => /usr/lib/libpyglib-2.0-python.so
libboost_python.so.5 (libc6) => /usr/lib/libboost_python.so.5
libboost_python.so (libc6) => /usr/lib/libboost_python.so
libboost_python-mt.so.5 (libc6) => /usr/lib/libboost_python-mt.so.5
libboost_python-mt.so (libc6) => /usr/lib/libboost_python-mt.so

다음 명령으로 컴파일 하였다.
$ g++ main2.cpp -o x -I/usr/include/python2.6 -pthread -lm -ldl -lutil 
/usr/lib/libpython2.6.so

7. 컴파일 후 실행 시 다음과 같은 에러 발생

  File "<string>", line 1
    sys.stdout.write('Hello from an embedded Python Script
                                                         ^
SyntaxError: EOL while scanning string literal
 
그래서 개행문자 \n를 제거하고 컴파일하여 결과를 확인하니 문제 없음.

8. 내가 작성한 모듈을 C언어에서 호출하기
mul.py
 def mul(num):
    return num * num    
전달인자로 받은 정수를 곱해서 리턴하는 모듈

main2.cpp
#include <stdio.h>
#include <Python.h>
int main(int argc, char * argv[])
{

// initialize the interpreter
    Py_Initialize();
  // evaluate some code
    PyRun_SimpleString("print ('hi')");
    PyRun_SimpleString("import mul");    
    PyRun_SimpleString("print mul.mul(2)");
    Py_Finalize();
  return 0;

파이썬 모듈을 임포트하고 임포트한 모듈을 호출하는 코드를 작성.

다음 명령으로 컴파일후 실행하면 에러 발생
 $ g++ main2.cpp -o x -I/usr/include/python2.6 -pthread -lm -ldl -lutil /usr/lib/libpython2.6.so
 [root@localhost python_test]# ./x
hi
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: No module named mul
Traceback (most recent call last):
  File "<string>", line 1, in <module>
NameError: name 'mul' is not defined
mul.py가 같은 디렉터리에 있는데도 모듈을 찾을수 없다는 메시지가 나옴

9. 최종 실행가능버전
위의 문제를 해결하기 위해 sys모듈의 path.append() 함수를 이용해 현재 작업 디렉터리를 라이브러리 패스에 추가해봄.
mul.py
 def mul(num):
    return num * num    
전달인자로 받은 정수를 곱해서 리턴하는 모듈

main2.cpp
 #include <stdio.h>
#include <Python.h>
int main(int argc, char * argv[])
{

// initialize the interpreter
    Py_Initialize();
  // evaluate some code
    PyRun_SimpleString("print ('hi')");

    PyRun_SimpleString("import sys");
    PyRun_SimpleString("sys.path");
//    PyRun_SimpleString("sys.path.append("/root/work/Twitter/Python/python_test")");
   PyRun_SimpleString("sys.path.append('/root/work/Twitter/Python/python_test')");
    PyRun_SimpleString("import mul");    
    PyRun_SimpleString("print mul.mul(2)");
    Py_Finalize();
  return 0;
}
컴파일하고 실행하면 위의 파란색 라인에서 문법오류가 나며 붉은색 라인처럼 "를 '로 수정하면 제대로 인식함.

결과
 [root@localhost python_test]# g++ main2.cpp -o x -I/usr/include/python2.6 -pthread -lm -ldl -lutil /usr/lib/libpython2.6.so
 [root@localhost python_test]# ./x
hi
4


__


Comments