So this is how I currently structure my files.
CPP Folder
Cython Folder
├── setup.py
└── Geometry
├── Circle
│ ├── __init__.py
│ ├── Circle.pyx
│ ├── Circle.pyi
│ └── Circle.pxd
└── Point
├── __init__.py
├── Point.pyx
├── Point.pyi
└── Point.pxd
And this is my setup.py file
from setuptools import setup, Extension, find_packages
from Cython.Build import cythonize
point_extension = Extension(
"Geometry.Point.Point",
[
"src/Geometry/Point/Point.pyx",
"../cpp/lib/src/Point.cpp"
],
include_dirs=[
"../cpp/lib/include"
],
libraries=["Some Library"],
library_dirs=[
"src/Geometry"
],
extra_compile_args=["-std=c++17", "-O3"],
language="c++"
)
circle_extension = Extension(
"Geometry.Circle.Circle",
[
"../cpp/lib/src/Circle.cpp",
"src/Geometry/Circle/Circle.pyx",
"../cpp/lib/src/Point.cpp"
],
include_dirs=[
"../cpp/lib/include"
],
libraries=["Some Library"],
library_dirs=[
"src/Geometry"
],
extra_compile_args=["-std=c++17", "-O3"],
language="c++"
)
setup(
name="Geometry",
version="0.1",
packages=find_packages(where="src"),
package_dir={"": "src"},
package_data={
"Geometry.Circle": ["*.so", "*.pyi"],
"Geometry.Point": ["*.so", "*.pyi"]
},
ext_modules=cythonize([point_extension, circle_extension],
compiler_directives={"language_level": 3},
include_path=[
"../../Expression/cython/src/Some Library",
"src/Geometry",
],
annotate=True),
zip_safe=False,
)
With this setup, when I wanna import Circle or Point for testing, I have to do as below:
from Geometry.Point import Point
from Geometry.Circle import Circle
And my goal is to be able to import them in this way: from Geometry import Circle, Point
So I think i should structure my file as follow:
CPP Folder
Cython Folder
├── setup.py
└── Geometry
├── __init__.py
├── Geometry.pyx
├── Geometry.pyi
├── Geometry.pxd
├── Circle
│ ├── __init__.py
│ ├── Circle.pyx
│ ├── Circle.pyi
│ └── Circle.pxd
└── Point
├── __init__.py
├── Point.pyx
├── Point.pyi
└── Point.pxd
How should I rewrite my setup.py and write my Geometry.pxd, .pyx and .pyi?
FYI this is a sample of my Point.pxd and Point.pyx
**[Point.pxd]**
from libcpp.memory cimport shared_ptr, weak_ptr, make_shared
from Bryan cimport _Bryan, Bryan
cdef extern from "Point.h":
cdef cppclass _Point:
_Point(shared_ptr[_Bryan] x, shared_ptr[_Bryan] y, shared_ptr[_Bryan] z)
shared_ptr[_Bryan] get_x()
shared_ptr[_Bryan] get_y()
shared_ptr[_Bryan] get_z()
cdef class Point:
cdef shared_ptr[_Point] c_point
**[Point.pyx]**
from Point cimport *
cdef class Point:
def __cinit__(self, Bryan x=Bryan("0", None), Bryan y=Bryan("0", None), Bryan z=Bryan("0", None)):
self.c_point = make_shared[_Point](x.thisptr, y.thisptr, z.thisptr)
def __dealloc(self):
self.c_point.reset()
def get_x(self) -> Bryan:
cdef shared_ptr[_Bryan] result = self.c_point.get().get_x()
cdef Bryan coord = Bryan("", None, make_with_pointer = True)
coord.thisptr = result
return coord
def get_y(self) -> Bryan:
cdef shared_ptr[_Bryan] result = self.c_point.get().get_y()
cdef Bryan coord = Bryan("", None, make_with_pointer = True)
coord.thisptr = result
return coord
def get_z(self) -> Bryan:
cdef shared_ptr[_Bryan] result = self.c_point.get().get_z()
cdef Bryan coord = Bryan("", None, make_with_pointer = True)
coord.thisptr = result
return coord
property x:
def __get__(self):
return self.get_x()
property y:
def __get__(self):
return self.get_y()
property z:
def __get__(self):
return self.get_z()
Thank you
>Solution :
This is a slightly speculative answer simply because I cannot build an example to compile the Cython modules now. I will assume that your setup.py is successful in compiling the modules.
You are correct with your proposed directory structure, though you really should use lowercase module names. So:
CPP Folder
cython Folder
├── setup.py
└── geometry
├── __init__.py
├── geometry.pyx
├── geometry.pyi
├── geometry.pxd
├── circle
│ ├── __init__.py
│ ├── circle.pyx
│ ├── circle.pyi
│ └── circle.pxd
└── point
├── __init__.py
├── point.pyx
├── point.pyi
└── point.pxd
You will need to change your setup.py to account for the lowercasing. Once you’ve done that, you can "hoist" (I don’t know if there’s a technical term for this) your classes up the directory hierarchy. Then they will be available under the parent (geometry) namespace
Inside __init__.py in the geometry directory, you put:
from .circle import Circle
from .point import Point
The remaining question is whether you even need the other files inside geometry. Once your Circle and Point classes are compiled, I’m not sure what you actually need in the geometry module to be compiled.