我有自己用Qt编写的C ++库项目(带有源代码),它使用QTcpsocket
,QUdpSocket
,QSerialPort
信号和插槽。
我也想在Python中支持这个库。
这样做的首选方式是什么?
因为这是SDK的一部分,所以同样适用于支持带有.NET的QT dll,这是支持Python之后的第二步。
Qt。
的API示例quint16 SendCommandAsync(CmdBaseSpv1* pcommand,
ConnectionArg connectionArg,
emitLogOptions::emitLogOption logOption,
LogInfo &txLogInfo,
LogInfo &rxLogInfo);
我想从Python调用此函数。
函数参数CmdBaseSpv1
,ConnectionArg
,emitLogOption
,LogInfo
都是Qt类。
其中一些参数使用QOBJECT
基类。
从功能名称中可以看出;它是一个异步函数调用。结果将发出信号,因此我也需要获得异步结果。
答案 0 :(得分:3)
我会写下我对包装C ++库的了解,并会尝试使用它,但作为一个巨大的免责声明,我只是将它用于非常非常简单的事情。
你问过用Python重写库。我会说这取决于。如果代码是微不足道的,那么我不明白为什么不。如果它更大并且必须与其他代码保持同步(正如你暗示.Net),我不会。为两者重用相同的代码是有意义的。
根据我对您的代码的看法,我会尝试使用boost::python或SWIG将其打包。
主要的麻烦是在Python中创建CmdBaseSpv1
,ConnectionArg
等。
如果您不需要任何Qt类来实例化您的类,这应该是直截了当的。但是,如果你需要Python内部的Qt类型(例如因为CmdBaseSpv1
的构造函数需要QString
),你的任务要复杂得多,因为你需要一种转换Python字符串的方法进入QString
。如果可以,您应该只使用stl
- 类型。
包装小型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是使用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 ++中的异常,那就太好了。