Неопределенная ссылка на ошибку `main` при встраивании Python в C

#python #c

#python #c

Вопрос:

Я пытаюсь встроить Python в C . Это мой файл Python (с именем EmbedTest.py ):

 from __future__ import division

class model:  
    def init(self,a,b):  
        self.a = a  
        self.b = b  
         def test_method(a,b):  
    m = model(a,b)  
    m.add(1)  
    print("a: ",a,"b: ",b)  
    return (a b,a-b,a*b)
  

Это мой файл C (с именем EmbedTest.cpp и находится в той же папке, что и EmbedTest.py )

 #include <Python.h>  

int main(int argc, char *argv[]) {  
    PyObject *pName, *pModule, *pFunc;  
    PyObject *pArgs, *pValue, *pValue_1, *pValue_2;  
    double sum,diff,prod;  
    double a = atof(argv[1]);  
    double b = atof(argv[2]);   
    Py_Initialize();  
    pName = PyUnicode_DecodeFSDefault("EmbedTest.py");  
    pModule = PyImport_Import(pName);  
    Py_DECREF(pName);  

    if(pModule != NULL) {
      pFunc = PyObject_GetAttrString(pModule,"test_method");    
      if(pFunc amp;amp; PyCallable_Check(pFunc)) {  
          pArgs = PyTuple_New(2);  
          pValue_1 = PyFloat_FromDouble(a);  
          pValue_2 = PyFloat_FromDouble(b);  
          if (!pValue_1) {
          Py_DECREF(pArgs);
            Py_DECREF(pModule);
        fprintf(stderr, "Cannot convert argumentn");
        return 1;  
        }  
        if (!pValue_2) {
        Py_DECREF(pArgs);
        Py_DECREF(pModule);
        fprintf(stderr, "Cannot convert argumentn");
        return 1;  
        }  
        PyTuple_SetItem(pArgs, 0, pValue_1);  
        PyTuple_SetItem(pArgs, 1, pValue_2);  
        
        pValue = PyObject_CallObject(pFunc, pArgs);  
            Py_DECREF(pArgs);  
            if (pValue != NULL) {
            sum = PyFloat_AsDouble(PyTuple_GetItem(pValue,0));
            diff = PyFloat_AsDouble(PyTuple_GetItem(pValue,1));
            prod = PyFloat_AsDouble(PyTuple_GetItem(pValue,2));  
              printf("a: %f b: %f sum: %f diff: %f prod: %f",a,b,sum,diff,prod);  
              Py_DECREF(pValue);  
            }  
            else {  
                Py_DECREF(pFunc);  
                Py_DECREF(pModule);  
                PyErr_Print();  
                fprintf(stderr,"Call failedn");  
                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;  }
  

Компиляция в порядке. Я использую флаги, предложенные python3.6-config --cflags . Следовательно

gcc -c -I/home/MyFolder/anaconda3/include/python3.6m -Wno-unused-result -Wsign-compare -march=nocona -mtune=haswell -ftree-vectorize -fPIC -fstack-protector-strong -O3 -pipe -fdebug-prefix-map==/usr/local/src/conda/- -fdebug-prefix-map==/usr/local/src/conda-prefix -fuse-linker-plugin -ffat-lto-objects -flto-partition=none -flto -DNDEBUG -fwrapv -O3 -Wall -Wstrict-prototypes EmbedTest.cpp

работает нормально.

Однако, когда я пытаюсь связать, у меня возникает проблема. Я использую флаги, предложенные python3.6-config --ldflags . Поэтому я пытаюсь

gcc -o EmbedTest.o -L/home/MyFolder/anaconda3/lib/python3.6/config-3.6m-x86_64-linux-gnu -L/home/MyFolder/anaconda3/lib -lpython3.6m -lpthread -ldl -lutil -lrt -lm -Xlinker -export-dynamic .

Однако я получаю следующее сообщение об ошибке:

 /usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/crt1.o: In function `_start':
/build/glibc-6V9RKT/glibc-2.19/csu/../sysdeps/x86_64/start.S:118: undefined reference to `main'
collect2: error: ld returned 1 exit status
  

Есть идеи, что здесь пошло не так?

Комментарии:

1. -o EmbedTest.o Это означает «создать выходной файл с именем EmbedTest.o». Вы перезаписываете объектный файл, который вы скомпилировали секунду назад.

2. @n.’местоимения’m. Спасибо! Однако, если я удалю «-o», я получу другую ошибку: поток байт-кода, созданный с помощью LTO версии 6.0 вместо ожидаемого 3.0, вы случайно не знаете, что это значит?

3. Вероятно, вы пытаетесь связать с двоичными /home/MyFolder/anaconda3 файлами, встроенными с помощью компилятора, намного более нового, чем ваш стандартный. Обновите свои инструменты или удалите -flto.

4. @n.’местоимения’m. Спасибо за предложения. К сожалению, удаление -flto ничего не меняет, ошибка все та же.

Ответ №1:

Вы не связываете файл .o, вы выводите его.

Изменить

 gcc -o EmbedTest.o -L/home/MyFolder/anaconda3/lib/python3.6/config-3.6m-x86_64-linux-gnu -L/home/MyFolder/anaconda3/lib -lpython3.6m -lpthread -ldl  -lutil -lrt -lm  -Xlinker -export-dynamic
  

Для

 gcc -o EmbedTest EmbedTest.o -L/home/MyFolder/anaconda3/lib/python3.6/config-3.6m-x86_64-linux-gnu -L/home/MyFolder/anaconda3/lib -lpython3.6m -lpthread -ldl  -lutil -lrt -lm  -Xlinker -export-dynamic
  

Комментарии:

1. Спасибо! К сожалению, обнаружилась какая-то новая проблема (см. Комментарии к моему исходному сообщению), но это, вероятно, связано со старыми инструментами.