通过模块

问题描述

我想做什么:安装一个暴露 c++ 类的 python/cython 模块,并且以后能够在任何 cimport 文件.pyx 它。

什么不起作用:一旦安装了模块,我就无法cimport 管理该文件。 cython 编译工作正常,因为我可以在纯 python 中使用包装类。

文件结构:

├── cytest
│   ├── cywrappers
│   │   ├── cynode.pxd
│   │   └── cynode.pyx
│   └── hpp
│       └── node.hpp
└── setup.py

node.hpp:

#ifndef graph_HPP
#define graph_HPP
class Node
{
public:
    int ID;
    double value;
    Node(){;};
    Node(int tid,double tvalue)
    {this->ID = tid; this->value = tvalue;}
    void multiplicate(double num){this->value = this->value * num;}
};
#endif

cynode.pxd

cdef extern from "node.hpp":
    cdef cppclass Node:
        Node()
        Node(int tid,double tvalue)
        int ID
        double value
        void multiplicate(double num)

cynode.pyx

cimport cynode
cdef class pynode:
    cdef cynode.Node c_node
    def __cinit__(self,int tid,double tval):
        self.c_node = cynode.Node(tid,tval)
    def print_val(self):
        print("ID: ",self.c_node.ID,"value: ",self.c_node.value)
    def multiplicate(self,mul):
        self.c_node.multiplicate(mul)

setup.py

from setuptools import setup,find_packages,Extension
from Cython.distutils import build_ext
import numpy as np
setup(
    name = "pycytest",packages=find_packages(include=['cytest','cytest.*']),package_data={'': ['*.pxd','*.pyx','*.hpp']},zip_safe=False,ext_modules=
        [Extension("cytest.cywrappers.cynode",sources = ["cytest/cywrappers/cynode.pyx"],language="c++",extra_compile_args=["-O3","-std=c++11"],include_dirs=["./cytest/hpp/",np.get_include()])],cmdclass = {'build_ext': build_ext}
)

我使用 pip install . 安装并尝试在 jupyter notebook(来自其他位置)中使用它。

import cytest.cywrappers.cynode as cynode
node = cynode.pynode(5,7.6)
node.print_val()
node.multiplicate(67)
node.print_val()

应有的输出

('ID: ',5,'value: ',7.6)
('ID: ',509.2)

但是,如果我尝试以下任何一行:

%%cython --cplus

# from cytest cimport cywrappers
# cimport cytest
# cimport cynode

我总是得到一个 'XXX.pxd' not found

有人有解决办法吗?我搜索了很长时间,恐怕找不到合适的关键字。

解决方法

我设法让它工作:

  • 我重命名了扩展名以适应 pyx
  • 我确保 pxd 在相对导入 (hpp) 中导入了 cdef extern from "../hpp/node.hpp":
  • 最后,为了让package_data能够找到并包含存储库中的所有文件(需要在后面的pyx中重用代码),我添加了一个空的__init__.py每个目录。

现在我可以cimport cytest.cywrappers.cynode as cynode

我尝试了很多东西,所以所有的编辑都不相关,但这里有一个有效的setup.py

from setuptools import setup,find_packages,Extension
from Cython.Distutils import build_ext
from Cython.Build import cythonize
import numpy as np

extension = cythonize( [Extension("cytest.cywrappers.cynode",sources = ["cytest/cywrappers/cynode.pyx"],language="c++",extra_compile_args=["-O3","-std=c++11"],include_dirs=["./cytest/hpp/",np.get_include()])],compiler_directives = {"language_level": 3,"embedsignature": True})

setup(
    name = "pycytest",packages=find_packages(include=['cytest','cytest.cywrappers']),package_data={"cytest": ["./*/*.pyx","./*/*.pxd","./*/*.hpp" ]},zip_safe=False,ext_modules=extension,cmdclass = {'build_ext': build_ext}

)