PySide2中的Slot, Signal以及emit该如何转化

参考PyCall包的入门教程, 我写了如下的例子

julia> using PyCall

julia> sys = pyimport("sys")
PyObject <module 'sys' (built-in)>

julia> pygui(:qt)
:qt

julia> PyCall.eventloops[:qt] = PyCall.qt_eventloop("PySide2", 50e-3)
Timer(Ptr{Nothing} @0x000000003131a650, Base.GenericCondition{Base.Threads.SpinLock}(Base.InvasiveLinkedList{Task}(Task (runnable) @0x000000001480ee10, Task (runnable) @0x000000001480ee10), Base.Threads.SpinLock(0)), true, false)

julia> QtWidgets = pyimport("PySide2.QtWidgets")
PyObject <module 'PySide2.QtWidgets' from 'D:\\Python\\Python37\\lib\\site-packages\\PySide2\\QtWidgets.pyd'>

julia> app = QtWidgets.QApplication(sys.argv)
PyObject <PySide2.QtWidgets.QApplication(0x3f02dce0) at 0x00000000245C2540>

julia> w = QtWidgets.QWidget()
PyObject <PySide2.QtWidgets.QWidget(0x3f3ca870) at 0x00000000408AB4C8>

lyt = QtWidgets.QVBoxLayout(w)
PyObject <PySide2.QtWidgets.QVBoxLayout(0x3f04c440) at 0x00000000408AB588>

julia> w.setLayout(lyt)
julia> btn = QtWidgets.QPushButton("Click me", w)
PyObject <PySide2.QtWidgets.QPushButton(0x3f3cadb0) at 0x00000000408AB648>

julia> lyt.addWidget(btn)

julia> function say_hello()
          msg = QtWidgets.QMessageBox(btn)
          msg.setText("Hello")
          msg.exec_()
      end
say_hello (generic function with 1 method)
julia> btn.clicked.connect(say_hello)
true

julia> w.show()

感觉勉强也可以运行, 但PySide2的教程中似乎用到@Slot()来修饰, 并用到emit以及Signal来处理,这才是QT消息循环机制的基础, 我们在Julia中该如何实现呢?