PythonC++:可以导入Armadillo (arma::),但不能导入子程序arma::arma_rng::randn。

问题描述 投票:0回答:1

问题

当用C++创建一个使用Armadillo的Python扩展时,我得到了错误。

A) 在Mac OS Mojave 10.14.4中,Python 3.7.5。

Traceback (most recent call last):
  File "./py_program.py", line 5, in <module>
    import cmodule
ImportError: dlopen(/Users/angel/.pyenv/versions/3.7.5/lib/python3.7/site-packages/cmodule.cpython-37m-darwin.so, 2): Symbol not found: __ZTWN4arma23arma_rng_cxx11_instanceE
  Referenced from: /Users/angel/.pyenv/versions/3.7.5/lib/python3.7/site-packages/cmodule.cpython-37m-darwin.so
  Expected in: flat namespace in /Users/angel/.pyenv/versions/3.7.5/lib/python3.7/site-packages/cmodule.cpython-37m-darwin.so

B) 在Ubuntu 20中,Python 3.8.2。

Traceback (most recent call last):
  File "./py_program.py", line 5, in <module>
    import cmodule
ImportError: /usr/local/lib/python3.8/dist-packages/cmodule.cpython-38-x86_64-linux-gnu.so: undefined symbol: _ZN4arma23arma_rng_cxx11_instanceE

这两个错误都是由于使用了 arma::arma_rng::randn<double>(),见下文。

如何解决?

详情

我想 py_program.py 中定义的C++模块(扩展)导入。cmodule.cpp.根据文件 https:/docs.python.org3extendingextending.html。 我有文件 py_program.py, setup.pycmodule.cpp.它们的内容是:

  1. py_program.py
#!/usr/bin/env python3

"""Import and use cmodule."""

import cmodule
cmodule.printvol(3.)
  1. setup.py
"""To install the module defined in cmodule.cpp."""
from distutils.core import setup, Extension
setup(name='cmodule', version='1.0',  \
      ext_modules=[
          Extension(
            'cmodule', ['cmodule.cpp'],
            extra_compile_args=['-std=c++11'],
            language='c++')],
      )
  1. cmodule.cpp
/* Module to be used in Python.
   All Python stuff follows Sec. 1.8 of 
   https://docs.python.org/3/extending/extending.html */
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <armadillo>


double f()
// Fails at using Armadillo.
// The module works if I delete this function.
{
    double rn_y = arma::arma_rng::randn<double>();
    return rn_y;
}


arma::cx_double g()
// Succeeds at using Armadillo.
{
    arma::cx_double value(0., 1.);
    return value;
}


static PyObject *
cmodule_printvol(PyObject *self, PyObject *args)
// A method of the module.
{
    double voltage;
    if (!PyArg_ParseTuple(args, "d", &voltage))
        return NULL;
    printf("voltage is %f.\n", voltage);
    Py_RETURN_NONE;
}


static PyMethodDef cmodule_methods[] = {
// Declare the modules methods.
    {"printvol", cmodule_printvol, METH_VARARGS, "Print voltage."},
    {NULL, NULL, 0, NULL}   /* sentinel */
};


static struct PyModuleDef cmodule = {
// Create the module.
    PyModuleDef_HEAD_INIT,
    "diff",
    NULL,
    -1,
    cmodule_methods
};

PyMODINIT_FUNC
PyInit_cmodule(void)
// Initialize the module.
{
    return PyModule_Create(&cmodule);
}

我运行它们的方法如下:

python setup.py install
python py_program.py

在Ubuntu中,以下文件的输出 python3 setup.py install 是。

running install
running build
running build_ext
building 'cmodule' extension
creating build
creating build/temp.linux-x86_64-3.8
x86_64-linux-gnu-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -fPIC -I/usr/include/python3.8 -c cmodule.cpp -o build/temp.linux-x86_64-3.8/cmodule.o -std=c++11
creating build/lib.linux-x86_64-3.8
x86_64-linux-gnu-g++ -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -g -fwrapv -O2 -Wl,-Bsymbolic-functions -Wl,-z,relro -g -fwrapv -O2 -g -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 build/temp.linux-x86_64-3.8/cmodule.o -o build/lib.linux-x86_64-3.8/cmodule.cpython-38-x86_64-linux-gnu.so
running install_lib
copying build/lib.linux-x86_64-3.8/cmodule.cpython-38-x86_64-linux-gnu.so -> /usr/local/lib/python3.8/dist-packages
running install_egg_info
Removing /usr/local/lib/python3.8/dist-packages/cmodule-1.0.egg-info
Writing /usr/local/lib/python3.8/dist-packages/cmodule-1.0.egg-info

导致问题的原因是:

double rn_y = arma::arma_rng::randn<double>();

事实上,如果我删除了函数 f()请注意,Armadillo被成功加载,因为 g() 是怎么回事?

python c++ armadillo python-c-api
1个回答
0
投票

在".py_program.py "文件中,行... setup.py争论 libraries=['armadillo']Extension() 解决了这个问题。

"""To install the module defined in cmodule.cpp."""
from distutils.core import setup, Extension
setup(name='cmodule', version='1.0',  \
      ext_modules=[
          Extension(
            'cmodule', ['cmodule.cpp'],
            extra_compile_args=['-std=c++11'],
            libraries=['armadillo'], // this solves the problem
            language='c++')],
      )

神秘地,没有它。arma:: 可以正确使用。但不是 "子模块",如 arma::arma_rng.

这个解决方案是通用的:同样的问题也会发生在其他库中。事实上,我在GNU科学库中重现了同样的问题(并使其工作)。libraries=['gsl']).

© www.soinside.com 2019 - 2024. All rights reserved.