python - Cython:使用distutils编译C++

标签 python c++ cython distutils

我正在尝试包装一些 C++ 神经网络代码,这样我就有了:

numpy -> double* -> armadillo

无论如何,我得到了典型的:

ImportError: dynamic module does not define init function

这显然是我的 distutils 配置有问题。这是我的项目的 MEW,以防有人发现错误:

设置.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

最佳答案

正在构建的模块名为 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++",
))

关于python - Cython:使用distutils编译C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34724841/

相关文章:

python - 在 matplotlib 中使用 hexbin 获取 bins 坐标

python - 错误: 'tuple' is not callable in python 3

c++ - 将 std::unique_ptr 用于 QMainWindow 时退出时出现 QT 应用程序段错误

python - 无法使用参数名称调用具有单个位置参数的 Cythonized 函数

python - 二进制 1d Numpy 数组到整数的最快一对一映射

python - 如何以 python 方式翻译此工作代码

python - 如何在 matplotlib 中使用自定义影线填充多边形?

c++ - "then in the quote directories"是什么意思?

c++ - 指针取消引用

python - 如何将一片 memoryview 转换为 C 字符串(unsigned char*)?