2016-01-11 4 views
3

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

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) 

EDIT: немного больше информации по запросу:

$ 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 
+0

Что делает 'readelf -Ws test.so | grep init' (или 'nm -gC test.so | grep init') сказать? –

+0

@AndreaCorbellini добавил (а) свой пост! ps: если я изменил имя общего объекта с «test» на «nnet_wrap», он может импортировать. Мне нужно будет проверить это сейчас ... –

ответ

1

модуль, который строится называется 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++", 
)) 
Смежные вопросы