«Экспортируемые» функции в модуле cython pyd

#python #cython

#python #cython

Вопрос:

Я использую 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. пожалуйста, опубликуйте данное решение в качестве ответа… вы можете получить несколько голосов и закрыть этот вопрос

Ответ №1:

Честно говоря, для вашего приложения вы, вероятно, не сможете. Способ сделать это — преобразовать ваши функции и классы в функции и классы 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 не поддерживают замыкания, и я полагаю, это означает, что они также не поддерживают генераторы.