如何用其他语言编写带有绑定的Qt插件系统

How to write Qt plugin system with bindings in other languages?

本文关键字:绑定 Qt 插件 系统 其他 何用 语言      更新时间:2023-10-16

我正在用Qt编写一个应用程序,我想用插件进行扩展。我的应用程序还有一个插件将使用的库。所以,我需要双向沟通。基本上,插件可以调用库,而加载插件的应用程序将调用它们。

现在,我的图书馆是用C++写的,所以它有一些类。插件可以包含头文件,链接到它并使用它。我还有一个带有我的接口的头文件,它是插件必须实现的抽象基类。他们还应该导出一个函数,该函数将返回指向该类的指针,并使用 C 链接。

到目前为止,我相信一切都很清楚,一个标准的插件接口。但是,有 3 个主要问题或子任务:

  1. 如何使用其他语言的库?我只用Python尝试过这个。我使用 SIP 生成了一个 Python 组件,我成功地将其导入到 test.py 文件中,并从库中的类调用函数。我没有尝试过任何其他语言。

  2. 如何为我的抽象类生成其他语言的适当声明或存根?由于插件必须实现这个类,我应该能够以某种方式生成一个等效于其他语言的标头,例如 Python 的.py文件、Java 的.class文件等。我还没有尝试过这个,但我想还有其他语言的生成器。

  3. 我将如何在插件中创建对象的实例?如果我到了这个地步,这个类将在插件中实现。现在我需要调用返回已实现抽象类实例的函数,并获取指向它的指针。根据我的研究,为了完成这项工作,我必须获得 Python 解释器、JVM 等的句柄,然后从那里与插件进行通信。

它看起来并不太复杂,但是当我开始研究时,即使是最简单的情况,也需要大量的工作。我只成功地达到了第一点,而且只在 Python 中。这让我怀疑我是否采取了正确的方法?你对此有何看法..也许我不应该在我的库和抽象基类中使用Qt,而应该只使用纯C++。这可能会让事情变得更容易一些。或者,也许我应该在我的库中只使用 C,并使插件返回 C 结构而不是类。我相信这会让事情变得容易得多,因为打电话给图书馆将是一件微不足道的事情。我相信实现 C 结构会比实现C++类容易得多,甚至比实现使用 Qt 对象的 C++ 类更容易。

请指出我正确的方向,并分享您在这方面的专业知识。另外,如果您知道有关该主题的任何书籍,我很乐意购买。或者一些处理这个问题的链接就可以了。

C++破坏

了它的符号,并具有特殊的魔力来定义类,这有点像在标准(C)对象文件之上被黑客入侵。您不希望其他语言的文件理解这种魔力。所以我肯定会遵循你自己的建议,用纯 C 做所有事情。

但是,这并不意味着您不能使用C++。只有接口必须是 C,而不是实现。或者更严格地说,生成的对象文件不得使用其他语言不使用的特殊功能。

虽然插件可以链接到您的程序并因此使用其中的函数,但我个人认为在加载插件函数后调用插件函数更具可读性(因此可维护),传递插件可以使用的函数指针数组。

  1. 每种语言都支持打开共享对象(SO 或 DLL)文件。使用它。

  2. 您的接口将包含具有多个参数和返回类型的函数,这些函数可能对它们的传入或检索方式有特殊需求。可能有自动化系统,但就我个人而言,我只会手动编写接口文件。最重要的是正确记录界面,以便人们可以使用他们想要的任何语言,只要他们知道如何从他们的语言加载对象文件。

  3. 不同的
  4. 语言具有非常不同的存储对象的方式。我建议使数据的创建者也是内存的所有者。因此,如果您的程序有一个带有构造函数的类(该构造函数包装在插件接口的 C 函数中),则该类是创建数据的类,并且您的程序而不是插件应该拥有它。这意味着插件需要通知你的程序,此时你的程序可以销毁它(当然,除非仍然需要它)。在支持它的语言中,例如Python和C++,当它们的接口对象被销毁时,可以自动完成此操作。(我在这里假设插件将创建一个对象以与实际对象进行通信;该对象的行为类似于真实对象,但使用目标语言而不是 C。

将任何库(如 Qt)排除在界面之外。您可以允许"将资源 #x 放在屏幕上的这个位置"等功能,但不允许"将此Qt对象放在屏幕上的这个位置"。原因是当你需要插件传递Qt对象时,它们需要理解Qt,这使得编写插件变得更加困难。

如果插件是完全受信任的,您可以允许它们传递(不透明)指向这些对象的指针,但对于与使用其他数字类型没有任何区别的接口。只是不要求它们对对象执行操作,除了调用程序中的函数。