【发布时间】:2020-01-23 12:33:31
【问题描述】:
我使用 cython 来包装 C++ 代码并使其在 Python 中可用。我面临的问题是我想使用一个包装的类作为我想要包装的函数中的参数。因此,从 Python 的角度来看,我想创建和修改包装类的对象,并将其用作我也想从 Python 调用的包装函数的参数。下面的代码有望证明这一点。
您可以在下面找到我想要包装的 C++ 中的最小示例:
./cppCode/Settings/Settings.h
class Settings
{
public:
Settings();
void doSomething();
};
./cppCode/Helper/Helper.h
#include "../Settings/Settings.h"
void myFunction(Settings settings);
功能并不重要。因此,我省略了 .cpp 文件。以下是到目前为止我在 Cython 中的方法:
./cythonCode/Settings/Settings.pxd
cdef extern from "../../cppCode/Settings/Settings.h":
cdef cppclass Settings:
Settings() except +
void doSomething()
./cythonCode/Settings/Settings.pyx
# distutils: sources = ../../cppCode/Settings/Settings.cpp
# distutils: language = c++
from Settings cimport Settings
cdef class PySettings:
cdef Settings c_settings
def __cinit__(self):
self.c_settings = Settings()
def doSomething(self):
self.c_settings.doSomething()
./cythonCode/Helper.pxd
from Settings.Settings cimport Settings
cdef extern from "../../cppCode/Helper/Helper.h":
void myFunction(Settings settings)
./cythonCode/Helper.pyx
# distutils: sources = ../../cppCode/Helper/Helper.cpp
# distutils: language = c++
from Helper cimport myFunction
cdef PyMyFunction(PySettings settings):
myFunction(settings)
运行.py
import cythonCode.Settings.Settings as Settings
#import cythonCode.Helper as Helper
mySettings = Settings.PySettings()
mySettings.doSomething()
#Helper.myFunction(mySettings) # not working
我希望项目的结构是清晰的。我实际上也想在文件夹“Helper”中拥有“Helper.pyx”和“Helper.pxd”,但是我不知道如何导入设置。如果您能帮我解决这个问题,我们将不胜感激。但是,主要问题是让 Helper 完全运行,以便我可以在“run.py”中使用它。 构建 cython 模块的“setup.py”看起来像这样:
from distutils.core import setup
from Cython.Build import cythonize
from setuptools.extension import Extension
extensions = [
Extension("Helper", ["Helper.pyx"])
]
setup(ext_modules=cythonize(extensions))
我在设置文件夹中单独做同样的事情。
非常感谢您帮助解决此问题!
EDIT:如cmets中所说,有两个错误:
1) 在run.py中应该是Helper.PyMyFunction(mySettings)。
2) PyMyFunction前面应该是def而不是cdef,因为我肯定想从Python调用这个函数。
EDIT2:我玩弄了您的输入,发现了一个不雅的解决方案,这导致了另一个问题。所以下面是对我有用的代码:
设置.pxd
cdef extern from "../../cppCode/Settings/Settings.h":
cdef cppclass Settings:
Settings() except +
void doSomething()
cdef extern from "../../cppCode/Helper/Helper.h":
void myFunction(Settings settings)
Settings.pyx
# distutils: sources = [../../cppCode/Settings/Settings.cpp, ../../cppCode/Helper/Helper.cpp]
# distutils: language = c++
from Settings cimport Settings, myFunction
cdef class PySettings:
cdef Settings c_settings
def __cinit__(self):
self.c_settings = Settings()
def doSomething(self):
self.c_settings.doSomething()
def PyMyFunction(PySettings settings):
myFunction(settings.c_settings)
当我对 Settings.pyx 进行 cythonize 时,我可以运行以下 Python 代码并且一切正常:
import Settings
mySettings = Settings.PySettings()
mySettings.doSomething()
Settings.PyMyFunction(mySettings)
我觉得不雅之处在于这两个部分(设置和 myFunction)都包含在同一个文件中。当这两个部分位于不同的文件中时,我不知道如何运行它。
EDIT3:为了解决“两个部分在不同文件中”的问题,请想象以下代码:
设置.pxd
cdef extern from "../../cppCode/Settings/Settings.h":
cdef cppclass Settings:
Settings() except +
void doSomething()
Settings.pyx
# distutils: sources = ../../cppCode/Settings/Settings.cpp
# distutils: language = c++
from Settings cimport Settings
cdef class PySettings:
cdef Settings c_settings
def __cinit__(self):
self.c_settings = Settings()
def doSomething(self):
self.c_settings.doSomething()
Helper.pxd
from Settings cimport Settings
cdef extern from "../../cppCode/Helper/Helper.h":
void myFunction(Settings settings)
Helper.pyx
# distutils: sources = ../../cppCode/Helper/Helper.cpp
# distutils: language = c++
from Helper cimport myFunction
def PyMyFunction(PySettings settings):
myFunction(settings.c_settings)
它与 EDIT2 中的代码相同,但分为两个文件。 Helper.pxd 中只有一行是“来自设置 cimport 设置”。但是,在 Helper.pyx 中出现此错误:
def PyMyFunction(PySettings settings):
^
---------------------------------------
Helper.pyx:6:17: 'PySettings' is not a type identifier
我尝试了“从设置 cimport PySettings”,但这不起作用。同样的错误不断发生。所有文件都在同一个目录中。
【问题讨论】:
-
@ead 我不相信这是正确的副本(或者如果它是正确的,我不太清楚)。这里的问题是1)
PyMyFunction是cdef而不是def,所以不能从Python调用; 2)OP调用myFunction(没有Py),我怀疑这只是一个错字。我很确定第 1 点有重复... -
鉴于您的编辑:您有什么问题?我可以在您的代码中看到一些小东西(您可能没有构建设置模块;不需要
cimport一个同名的 pxd;在 helper.pxd 中您可能也想导入PySettings),但这看起来基本正确,我认为错误消息应该足够清晰,您可以修复它们。 -
我进行了第二次编辑。现在基本上是一个完全不同的问题。除非这很容易解决,否则我可能应该打开一个新问题。
标签: python c++ cython cythonize