Что означает этот ImportError при импорте моего модуля c ?

#python #c

#python #c

Вопрос:

Я работал над написанием модуля Python на C . У меня есть программа на C , которая может работать сама по себе. Он отлично работает, но я подумал, что было бы лучше, если бы я мог вызвать его как функцию из Python. Итак, я приложил все усилия, и он создает и устанавливает. Вот код для моего модуля (вызывается nnrunner.cpp ):

 #include <Python.h>
#include <vector>
#include "game.h"
#include "neuralnetai.h"

using namespace std;

/**************************************************
 * This is the actual function that will be called
 *************************************************/
static int run(string filename)
{
    srand(clock());
    Game * pGame = new Game();

    vector<int> topology;
    topology.push_back(20);

    Network net(31, 4, topology);

    net.fromFile(filename);

    NNAI ai(pGame, net);

    pGame->setAI(amp;ai);

    while (!pGame->isGameOver())
        pGame->update(NULL);

    return pGame->getScore();
}

static PyObject *
nnrunner_run(PyObject * self, PyObject * args)
{
    string filename;
    int score;
    if (!PyArg_ParseTuple(args, "s", amp;filename))
        return NULL;
    score = run(filename);
    return PyLong_FromLong(score);
}

static PyMethodDef NnrunnerMethods[] = {
        {"run",  nnrunner_run, METH_VARARGS,
         "Run the game and return the score"},
        {NULL, NULL, 0, NULL}        /* Sentinel */
};

static struct PyModuleDef nnrunnermodule = {
        PyModuleDef_HEAD_INIT,
        "nnrunner",   /* name of module */
        NULL, /* module documentation, may be NULL */
        -1,       /* size of per-interpreter state of the module,
                or -1 if the module keeps state in global variables. */
        NnrunnerMethods
};

PyMODINIT_FUNC
PyInit_nnrunner(void)
{
    PyObject *m;

    m = PyModule_Create(amp;nnrunnermodule);
    if (m == NULL)
        return NULL;

    return m;
}
  

И мой сценарий сборки (вызывается setup.py ):

 from distutils.core import setup, Extension

module1 = Extension('nnrunner',
                    sources = ['nnrunner.cpp', 'game.cpp', 'uiDraw.cpp', 
                    'uiInteract.cpp', 'player.cpp', 'ship.cpp', 'network.cpp'],
                    libraries = ['glut', 'GL', 'GLU'])

setup (name = 'NNRunner',
       version = '1.0',
       description = 'This is my first package',
       ext_modules = [module1])
  

Он должен компилироваться из -lglut -lGL -lGLU -за зависимости, но на самом деле у него нет никакого пользовательского интерфейса.
Я могу скомпилировать его и установить ( python setup.py build , python setup.py install ), но когда я пытаюсь его импортировать, я получаю ошибки:

 Python 3.5.2 |Anaconda 4.2.0 (64-bit)| (default, Jul  2 2016, 17:53:06) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import nnrunner
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: /home/justin/anaconda3/lib/python3.5/site-packages/nnrunner.cpython-35m-x86_64-linux-gnu.so: undefined symbol: _ZTVNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEEE
>>> 
  

Может ли кто-нибудь указать мне направление документации по этому поводу? Это первый раз, когда я пытаюсь создать модуль Python на C .

Ответ №1:

Скорее всего, это означает, что вы импортируете общую библиотеку, которая имеет двоичный интерфейс, несовместимый с вашим дистрибутивом Python.

Итак, в вашем случае: у вас 64-разрядный Python, и вы импортируете 32-разрядную библиотеку или наоборот. (Или, как предложено в комментарии, используется другой компилятор).

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

1. Или, возможно, другой компилятор. Это часто случается при компиляции C в OS X.

2. Я знаю, что у меня есть 64-разрядный интерпретатор Python. Итак, для ясности вы говорите, что, возможно <vector> , то, что я включаю, является 32-разрядным, или, возможно, какая-то другая подобная библиотека 32-разрядная? Как бы мне выяснить, является ли конкретная библиотека 32 или 64-разрядной? Или что он был скомпилирован с помощью другого компилятора, отличного от того, который использует мой скрипт сборки Python?

3. @justinrixx Нет. Я говорю, что компилятор, который вы используете, создает 32-разрядные двоичные файлы. Это одна из возможностей. Еще одна возможность заключается в том, что компилятор, создавший исполняемый файл Anaconda, не является тем же компилятором, который создал ваш lib-файл. Попробуйте импортировать вашу библиотеку в стандартный Python, который поставляется с вашим дистрибутивом Linux. Какой дистрибутив Linux вы используете? Если Debian / Ubuntu, установите Python с sudo apt-get install python3 помощью , а затем запустите python3 и импортируйте свой модуль и посмотрите, что произойдет.

4. @TheQuantumPhysicist Да, я использую Ubuntu. При использовании я получаю ту же ошибку python3 , что и с Anaconda. Когда я запустил python setup.py build его, он запустил некоторые вещи g . Но разве .so это не должно быть построено с той же архитектурой, что и интерпретатор по умолчанию (который, я думаю, является Anaconda)?

5. @justinrixx Anaconda — это дистрибутив Python. Попробуйте установить собственный Python, который поставляется с вашей Ubuntu. Честно говоря, я не понимаю, зачем вам вообще нужна Anaconda в Ubuntu, но в любом случае мы должны убедиться, что вы понимаете, что Anaconda является иностранным дистрибутивом Python в вашей операционной системе и, возможно, скомпилирована с другим компилятором. Мне нужно, чтобы вы попытались импортировать вашу библиотеку на родном Python вашей операционной системы. Он должен быть расположен в /usr/bin/Python3 (или аналогично).

Ответ №2:

была аналогичная проблема с модулем cython от multivec. я предполагаю, что существует проблема несовместимости между компилятором и библиотекой Anaconda.

решаемая проблема путем обновления libgcc пакета Anaconda: conda install libgcc