Cython pyd模块中的“导出”函数

3 投票
1 回答
2036 浏览
提问于 2025-04-18 11:25

我正在使用cython将我的Python脚本编译成一个.pyd模块。我的Python脚本如下:

    class WorkingThread(QtCore.QThread):
    ...
    class Ui_Dialog(object):
    ...
    def Function1():
    ...
    def Function2():
    ...
    def main():
    ...

我该如何让所有的类和函数只能在编译后的模块内部使用?也就是说,我希望这个.pyd模块只“导出”main()函数,其他的都不想让外部访问。

编辑:一个来自cython-users的朋友给了我解决方案:预先声明类为

cdef object MyClass

所以我的代码应该看起来像这样

cdef object WorkingThread
cdef object Ui_Dialog
class WorkingThread(QtCore.QThread):
...
class Ui_Dialog(object):
...
cdef Function1():
...
cdef Function2():
...
def main():
...

1 个回答

0

老实说,对于你的应用来说,可能做不到。要实现这个目标,你需要把你的函数和类转换成cdef函数和类,然后从你的主函数中调用它们。不过,如果你想从普通的Python类(比如QThread)派生,就无法完全隐藏所有内容。下面是一个例子,展示了哪些内容会被暴露,哪些不会:

def Function1():
    # This function will be exposed
    pass

cdef Function2():
    # But this cdef function will not
    pass

cdef class UI_Dialog: 
    # This class will be exposed

    cdef object storage # This member won't be exposed

    def def_func(self): 
        # This member function will be available
        pass

    cdef cdef_func(self):
        # But this one will not be available
        pass

#cdef class WorkingThread(QTCore.QThread):
    # This wouldn't even compile; cdef classes can't
    # derive from non cdef classes

class WorkingThread(QTCore.QThread):
    # This is a normal python class, and is exposed

    def __init__(self):
        #You're free to call cdef functions in here
        Function2()
        self.dialog = UI_Dialog()

        #But you can't access cdef members,
        #So the following wouldn't compile
        #self.dialog.storage
        #self.dialog.cdef_func()

        # But you can access def members
        self.dialog.def_func()

cdef hidden_main():
    # This function isn't exposed, and you can also call
    # cdef functions in here, and access cdef members
    Function1()
    Function2()
    dialog = UI_Dialog()
    dialog.def_func()
    dialog.cdef_func()
    dialog.storage = dict()
    workingThread = WorkingThread()

def main():
    # Here you can just call your hidden_main
    hidden_main()

基本上,你想隐藏的任何逻辑都需要放在cdef函数里,类是无法隐藏的,但你可以限制这些类成员的访问。如果你想隐藏一个类的成员,它必须是一个cdef类,而这些类不能从Python类派生。

还要注意的是,你不能简单地把任何普通的Python函数变成cdef函数(虽然我认为这最终是目标)。目前,cdef函数不支持闭包,我相信这也意味着它们不支持生成器。

撰写回答