子目录结构破坏了C ++扩展版本

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

我似乎无法解决使用子目录结构时导入C ++扩展模块不再起作用的问题。

下面的两个案例代表一个简单的工作案例,以及一个稍作改动的案例,我一生无法工作。

方案1(正在工作)

项目树:

demo_cext/         # Current working directory for all of this
├── _cmodule.cc
└── setup.py

setup.py的内容:

import setuptools

module = setuptools.Extension("_cmod", sources=["_cmodule.cc"], language="c++")

if __name__ == "__main__":
    setuptools.setup(name="cmod", ext_modules=[module])

_cmodule.cc的内容,基本上是C扩展的世界,它创建不带参数且返回5的函数foo()

#define PY_SSIZE_T_CLEAN
#include <Python.h>

static PyObject *
foo(PyObject *self, PyObject *args) {
    /* noargs() */
    if (!PyArg_ParseTuple(args, "")) {
        return NULL;
    }
    return PyLong_FromLong(5);
}

static PyMethodDef FooMethods[] = {
    {"foo",  foo,      METH_VARARGS,  "Do the foo"},
    {NULL,   NULL,     0,             NULL}
};

PyDoc_STRVAR(module_doc, "This is the module docstring.");
static struct PyModuleDef cmodule = {
    PyModuleDef_HEAD_INIT,
    "cmod",
    module_doc,
    -1,
    FooMethods,
    NULL,
    NULL,
    NULL,
    NULL
};

PyMODINIT_FUNC
PyInit__cmod(void) {
    PyObject* m = PyModule_Create(&cmodule);
    if (m == NULL) {
        return NULL;
    }
    return m;
}

整个过程就像一个咒语:

$ python3 -V
Python 3.7.4
$ python3 setup.py build install
>>> import _cmod
>>> _cmod.foo()
5

方案2(破碎)

重新调整项目布局:

$ rm -rf build/ dist/ cmod.egg-info/ && \
> mkdir cmod/ && touch cmod/__init__.py && \
> mv _cmodule.cc cmod/

留给我:

demo_cext/         # Current working directory for all of this
├── cmod
│   ├── __init__.py
│   └── _cmodule.cc
└── setup.py

我稍微更改setup.py

import setuptools

module = setuptools.Extension("cmod._cmod", sources=["cmod/_cmodule.cc"], language="c++")

if __name__ == "__main__":
    setuptools.setup(name="cmod", ext_modules=[module])

现在再次运行:

$ python3 setup.py build install

尝试导入模块使我有了:

>>> from cmod import _cmod
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name '_cmod' from 'cmod' (.../demo_cext/cmod/__init__.py)
>>> import cmod._cmod
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'cmod._cmod'

这里我有什么问题?我确信使用命名约定很简单。

python c++ python-3.x python-c-api
1个回答
0
投票

[在启动Python之前尝试更改目录(例如cd ..)。追溯表明您在cmod(您的源目录,而不是安装目录)中找到了demo_cext/cmod,但是构建的扩展名不存在(在demo_cext/build之后的build中,并且您的系统站点软件包目录install之后。

如果只能在Python 3上使用,另一种解决方案是摆脱cmod/__init__.py文件;多亏了__init__.py,在Python 3中制作一个包并不需要一个空的PEP 420文件。通过删除__init__.py,隐式名称空间包装将接管,它应自动在cmod中的all sys.path包中搜索您要导入的子模块。

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