본문 바로가기
개발 업무(코딩)-개발자였을때 썼던..

embedded python with C

by 주용사 2023. 1. 9.
728x90

pModule이 Null이 나온다면 import부터 체크해보자

탭으로 구분되어있나 띄어쓰기로 되어있나

제대로 def main이 되어있나

---------------------------------------------------------

20200805 추가

하위디렉토리로 만약에 파이썬파일이 import 되어있다면 ...

가정 1. 하위디렉토리 명은 abc이다.

가정 2. c에서 콜할 메인에서 import abc 를 하고 있다

가정 3. ./abc/in.py라는 파일안에 클래스가 선언되어있다.

가정 4. in.py 안에 import abc.utils 등으로 import 되어있다.

---> 수정하는 방법

c파일인 main.c에서 path를 한번더 추가시켜줘야한다.

PyList_Append(pPath, PyUnicode_FromString("메인함수있는경로")

-> 추가필요 : PyList_Append(pPath, PyUnicode_FromString("메인함수있는경로/abc")

를 추가해야한다.

가정2에서 import abc -> import in 으로 바꾼다.

가정4에서 import abc.utils -> import utils로 바꾼다.

---------------------------------------------------------------------

20200515 추가

개인적으로 소스 파일을 수정한 것을 적어놓는다.

- 전체 main을 만들고 그 안에서 초기화 및 데이터 넣어주는 작업을 했는데 같은 영역 안에있어도 값이 달랐다.

def main

a

func(a)

a

이런 형태라고 하면 func을 거친 a는 값이 달라져야하는데 안달라져있었다. 그렇기 때문에

def main

a

a = func(a)

a

아래와 같은 방법을 취했고 func에는 return 값을 주었다.

밑에는 c소스 이다. 이 소스는 파이썬한테 아규먼트를 전달하여 실행을 시키고 결과 값을 받아오게 할 수 있는 소스이다.

c 소스에서 중요한점

1. 경로설정

2. 파이썬에서 return 받는 값이 있어야한다.(파이썬에서 주는 형식을 그대로 받고 싶다) [0, 1, 2, ...] or TEXT or 100.00

3. return 값에 따라 다르게 pValue를 받아올 수 있다.

실행시킬 python 소스에서 중요한점

1. return 의 데이터 타입. c가 받는 형식대로 뿌려줘야한다. 문자열이면 문자열, 숫자면 숫자

2. sys.argv와 self의 기능을 사용할 수가 없다(나는 그러했다)

3. ./a.out mypython main 1 2 3 이런식을 실행시킬 수 있다.

a.out은 실행파일

mypython은 파이썬 소스 파일(mypython.py)

main은 파이썬 내에 선언된 함수(def main(a, b, c):)

print(a) print(b) print(c)를 할 경우 1 2 3이 출력된다.

4. 위와 같은 이유로 어쩔 수 없이 수정이 되어야하며 나의 경우는 def main을 따로 만들어서 아규먼트를 받아오고 init을 했으며 소스의 플로우대로 실행시켜나갔다.

-----------------------

Exception ignored in: <module 'threading' from '/usr/lib64/python3.6/threading.py'>

Traceback (most recent call last):

File "/usr/lib64/python3.6/threading.py", line 1289, in _shutdown

assert tlock.locked()

SystemError: <built-in method locked of _thread.lock object at 0x7ff2db729878> returned a result with an error set

위와같은 오류 때문에 애먹었는데 c와 python의 리턴주고 받는 데이터 형식이 달라서 였다.

세그멘테이션 폴트는 흔하게 발생할 것이다.

 

#include<stdio.h>
#include<Python.h>

int main(int argc, char *argv[])
{
        PyObject *pName, *pModule, *pFunc, *pPath, *pDict;
        PyObject *pArgs, *pValue;
        int i;

        if (argc < 3) {
                fprintf(stderr,"Usage: call pythonfile funcname [args]\n");
                return 1;
        }

        // Initialize the Python Interpreter
        // Python 인터프리터 초기화
        Py_Initialize();
        // unix 에서는 현재 경로에 python source(??.py) 가 있더라도
        // 반드시 경로를 지정 하여야 한다.
        pPath = PySys_GetObject("path");

        PyList_Append(pPath, PyUnicode_FromString( "/home/changjo/pytoc" ));

        pName = PyUnicode_DecodeFSDefault(argv[1]);

        //pName = PyUnicode_FromString(argv[1]);

        pModule = PyImport_Import(pName);

        pDict = PyModule_GetDict(pModule);

        //pFunc = PyDict_GetItemString(pDict, argv[2]);

        /* Error checking of pName left out */

        Py_DECREF(pName);

        if (pModule != NULL) {
                pFunc = PyObject_GetAttrString(pModule, argv[2]);
                /* pFunc is a new reference */

                if (pFunc && PyCallable_Check(pFunc)) {
                        pArgs = PyTuple_New(argc - 3);
                        for (i = 0; i < argc - 3; ++i) {
                                pValue = PyUnicode_FromString(argv[i + 3]); // string형태로 넣어주는 방법
                                //pValue = PyLong_FromLong(atoi(argv[i + 3]));
                                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);
                        }
                printf("pArgs : %s\n", PyUnicode_AsUTF8(PyObject_Repr(pArgs))); // PyObject -> String
                        pValue = PyObject_CallObject(pFunc, pArgs);
                        //Py_DECREF(pArgs);
                        if (pValue != NULL) {
                                printf("pValue : %s\n", PyUnicode_AsUTF8(PyObject_Repr(pValue))); // PyObject -> String
                                //printf("pValue : %s\n", pValue);
                                //printf("Result of call: %ld\n", PyLong_AsLong(pValue));
                                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;
        }
        if (Py_FinalizeEx() < 0) {
                return 120;
        }
        return 0;
}
728x90