#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