Python支持Qt dll

时间:2017-01-24 10:06:42

标签: python c++ qt pyqt wrapper

我有自己用Qt编写的C ++库项目(带有源代码),它使用QTcpsocketQUdpSocketQSerialPort信号和插槽。

我也想在Python中支持这个库。

这样做的首选方式是什么?

  • 用Python编写包装器,如果有的话有障碍吗?
  • 不知道PyQt是否只是为了这个目的?
  • 或者你认为通过实现C ++库项目中使用的逻辑来更好地用Python重写lib。

因为这是SDK的一部分,所以同样适用于支持带有.NET的QT dll,这是支持Python之后的第二步。

Qt。

的API示例
quint16 SendCommandAsync(CmdBaseSpv1* pcommand,
                         ConnectionArg connectionArg,
                         emitLogOptions::emitLogOption logOption,
                         LogInfo &txLogInfo,
                         LogInfo &rxLogInfo);

我想从Python调用此函数。 函数参数CmdBaseSpv1ConnectionArgemitLogOptionLogInfo都是Qt类。 其中一些参数使用QOBJECT基类。

从功能名称中可以看出;它是一个异步函数调用。结果将发出信号,因此我也需要获得异步结果。

1 个答案:

答案 0 :(得分:3)

我会写下我对包装C ++库的了解,并会尝试使用它,但作为一个巨大的免责声明,我只是将它用于非常非常简单的事情。

你问过用Python重写库。我会说这取决于。如果代码是微不足道的,那么我不明白为什么不。如果它更大并且必须与其他代码保持同步(正如你暗示.Net),我不会。为两者重用相同的代码是有意义的。

我的建议

根据我对您的代码的看法,我会尝试使用boost::pythonSWIG将其打包。

如何包装

主要的麻烦是在Python中创建CmdBaseSpv1ConnectionArg等。

如果您不需要任何Qt类来实例化您的类,这应该是直截了当的。但是,如果你需要Python内部的Qt类型(例如因为CmdBaseSpv1的构造函数需要QString),你的任务要复杂得多,因为你需要一种转换Python字符串的方法进入QString。如果可以,您应该只使用stl - 类型。

Python中的一切

包装小型C库的最简单方法是使用cffi module(或ctypes)。您可以在Python中编写完整的绑定。但是,如果您的API很大并且可能会变得困难,那么这是很多手动工作。

还有另一个问题:ctypes是only compatible with C,而不是C ++。所以你需要改变你的界面以与C兼容,在内部你仍然可以使用C ++和Qt。

手工包裹

另一种方法是自己包装库调用。您可以使用Python API执行此操作。还有一些库可以帮助您创建绑定。 Boost::python似乎特别有前途并且适用于C ++。

绑定生成器

如果你的API非常大,你应该使用一个绑定生成器来解析C ++代码并自己生成绑定。例如sip就是其中之一。它用于为整个Qt库创建绑定。有一些绑定生成器,Python文档中提到的一个是SWIG。 PySide使用Shiboken,并在其网站上对其进行了很好的描述。

SWIG还有一个额外的好处,即您可以为多种语言创建绑定,包括C#。

的PyQt

PyQt是使用sip从Qt生成的绑定。您可能不需要它,除非您需要从Python内部访问Qt的全部功能。如果是这种情况,请考虑使用sip来生成绑定,因此信号槽机制之类的东西在您的库和PyQt之间是兼容的。

绑定的挑战

绑定带来一些挑战,因为Python和C ++在某些关键领域有所不同。

内存管理

Python中的内存管理几乎是自动的,在C ++中你需要手动完成。例如

def myfunc():
    mywidget = QWidget()

myfunc()末尾mywidget收集垃圾。但是在C ++中

void myfunc() {
    auto mywidget = new QWidget();
}

mywidget仍然存在。这意味着即使在Python内部,您也需要处理C ++内存管理。我看到的问题是内存泄漏和悬空指针。使用回调时要注意这一点,你不希望Python在C ++认为它还活着的时候垃圾收集回调。

例外

并非所有编程语言都有异常或以相同方式处理它们。例如,如果可以在Python中捕获C ++中的异常,那就太好了。

相关问题的链接