Python — Cython: использование distutils для компиляции переполнения стека

Я пытаюсь обернуть некоторый код нейронной сети C ++, чтобы у меня было:

numpy -> double* -> armadillo

Во всяком случае, я получаю типичное:

ImportError: dynamic module does not define init function

Это явно что-то не так в моей конфигурации distutils. Вот MEW моего проекта на тот случай, если кто-то может исправить ошибку:

setup.py

#!/usr/bin/env python build_ext --inplace
# -*- coding: utf-8 -*-

# to run:
# python setup.py build_ext --inplace

from distutils.core import setup, Extension
from Cython.Build import cythonize

setup(
name='My Test',
ext_modules = cythonize(Extension(
"test",
sources=["nnet_wrap.pyx", "nnet.cpp"],
libraries = ['armadillo'],
language="c++",
)))

nnet_wrap.pyx

import numpy as np
cimport numpy as np

cdef extern from "nnet.h":
void nnet_fit(int D, int N, double* X, double* Y)class WrapNN:
def nnet_fit(self, np.ndarray[np.double_t, ndim=2] X):
X = np.ascontiguousarray(X)
cdef np.ndarray[np.double_t, ndim=1] y = np.zeros((len(X),), dtype=np.double)
nnet_fit(X.shape[1], X.shape[0], &X[0,0], &y[0])
return y

nnet.h

void nnet_fit(int D, int N, double* X, double* Y);

nnet.cpp

#include <armadillo>
using namespace arma;

void nnet_fit(int D, int N, double* X, double* Y)
{
mat _X(X, N, D, false);
// do work
vec _Y;  // results
for(int i = 0; i < N; i++)
Y[i] = _Y[i];
}

Я знаю, что это немного хакерски. Во всяком случае, он прекрасно компилируется и генерирует test.so файл, но затем не удается импортировать:

$ python setup.py build_ext --inplace
$ python
>>> import test
ImportError: dynamic module does not define init function (inittest)

РЕДАКТИРОВАТЬ: дополнительная информация по запросу:

$ readelf -Ws test.so | grep init
118: 0000000000003168     0 FUNC    GLOBAL DEFAULT    9 _init
123: 000000000000ab90   160 FUNC    WEAK   DEFAULT   11 _ZN4arma3MatIdE9init_coldEv
126: 0000000000009ae0  4211 FUNC    GLOBAL DEFAULT   11 initnnet_wrap
42: 00000000000036e0    79 FUNC    LOCAL  DEFAULT   11 _ZL30__Pyx_CyFunction_init_defaultsP22__pyx_CyFunctionObject
202: 000000000020f3e0     1 OBJECT  LOCAL  DEFAULT   24 _ZStL8__ioinit
211: 000000000020dce0     0 OBJECT  LOCAL  DEFAULT   17 __frame_dummy_init_array_entry
306: 0000000000009ae0  4211 FUNC    GLOBAL DEFAULT   11 initnnet_wrap
330: 000000000000ab90   160 FUNC    WEAK   DEFAULT   11 _ZN4arma3MatIdE9init_coldEv
344: 0000000000003168     0 FUNC    GLOBAL DEFAULT    9 _init

Кстати, моя версия Cython от Ubuntu 14.04 может быть немного устаревшей. Я знаю, что некоторые синтаксис был изменен с distutils. Скажите, если вы думаете, что это может быть проблемой.

$ dpkg -s cython | grep Version
Version: 0.20.1+git90-g0e6e38e-1ubuntu2

3

Решение

Строящийся модуль называется nnet_wrap, но выходной файл называется test.so, Это подтверждается тем фактом, что ваш test.so содержит символ с именем initnnet_wrap (Вместо этого Python неправильно ищет inittest).

В определении вашего расширения замените 'test' с 'nnet_wrap', так что Python может найти правильный символ.

ext_modules = cythonize(Extension(
"test",
#    ^^^^
sources=["nnet_wrap.pyx", "nnet.cpp"],
#             ^^^^^^^^^
libraries = ['armadillo'],
language="c++",
))
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]