我具有以下目录结构:
testcython/
setup.py
testcython/
__init__.py
foo.pyx
stuff.py
bar/
__init__.pxd
__init__.py
bar.pxd
bar.pyx
文件内容如下:
bar.pxd
cdef struct constants:
double a
double b
double c
cdef class Constants:
cdef constants consts
bar.pyx
cdef class Constants:
def __cinit__(self):
self.consts.a = 1.0
self.consts.b = 2.0
self.consts.c = 3.0
@property
def a(self):
return self.consts.a
@property
def b(self):
return self.consts.b
@b.setter
def b(self, double value):
self.consts.b = value
self.consts.a = self.consts.c / (2.0 * value)
@property
def c(self):
return self.consts.c
foo.pyx
from testcython.bar.bar cimport Constants, constants
cdef do_something_fast(constants* consts):
return consts.a
cpdef do_something(Constants consts_cls):
cdef:
constants* consts = &consts_cls.consts
return do_something_fast(consts)
stuff.py
from __future__ import print_function
from testcython.bar.bar import Constants
from testcython.foo import do_something
class Thing:
def __init__(self):
self.constants = Constants()
def do():
thing = Thing()
print(do_something(thing.constants))
setup.py
import os, sys
from Cython.Build import build_ext, cythonize
from setuptools import setup, Extension, find_packages
def ext_modules():
import numpy as np
include_dirs = ['.', np.get_include()]
root_dir = os.path.abspath(os.path.dirname(__file__))
bar_ext = Extension(
"bar.bar",
sources=[root_dir + "/testcython/bar/bar.pyx"],
include_dirs=include_dirs,
)
foo_ext = Extension(
"foo",
sources=[root_dir + "/testcython/foo.pyx"],
include_dirs=include_dirs
)
exts = [bar_ext, foo_ext]
return cythonize(exts, language_level=3, annotate=True)
REQUIREMENTS = [
"numpy",
"cython"
]
setup(
name="testcython",
packages=find_packages(),
ext_package="testcython",
ext_modules=ext_modules(),
cmdclass={"build_ext" : build_ext},
zip_safe=False,
package_data={
"testcython" : ["bar/*.pxd",]
},
install_requires=REQUIREMENTS
)
testcython/__init__.py
from .stuff import do
问题
一切正常,仅在运行时就会出现问题:
import testcython
在Python环境中。这将导致以下错误:
>>> import testcython
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/path/to/testcython/testcython/__init__.py", line 1, in <module>
from .stuff import do
File "/path/to/testcython/testcython/stuff.py", line 6, in <module>
from testcython.foo import do_something
File "testcython/bar/bar.pxd", line 6, in init foo
cdef class Constants:
ValueError: testcython.bar.bar.Constants size changed, may indicate binary incompatibility. Expected 40 from C header, got 16 from PyObject
尝试在类Constants
中包装指向C语言的非指针结构是否有问题?还是其他?