我正在Qt中编写一个我想用插件扩展的应用程序。 我的应用程序还有一个插件将使用的库。所以,我需要双向沟通。基本上,插件可以调用库,加载插件的应用程序将调用它们。
现在,我的库用C ++编写,所以它有一些类。插件可以包含头文件,链接到它并使用它。我的接口也有一个头文件,这是插件必须实现的抽象基类。他们还应该导出一个函数,该函数将返回指向该类的指针,并使用C链接。
到目前为止,我相信一切都很清晰,一个标准的插件界面。但是,有3个主要问题或子任务:
如何使用其他语言的图书馆? 我只用Python试过这个。我使用SIP生成了一个Python组件,我在test.py文件中成功导入了该组件,并从库中的类调用了函数。我没有尝试过任何其他语言。
如何为其他语言的抽象类生成适当的声明或存根?由于插件必须实现此类,因此我应该能够以某种方式生成与其他语言中的标头等效的文件,例如Python的.py文件,Java的.class文件等。 我还没有尝试过,但我想有其他语言的生成器。
我如何在插件中创建对象的实例?如果我达到这一点,该类将在插件中实现。现在我需要调用返回已实现的抽象类的实例的函数,并获取指向它的指针。 根据我的研究,为了完成这项工作,我将不得不掌握Python解释器,JVM等,然后从那里与插件进行通信。
看起来并不太复杂,但是当我开始研究时,即使是最简单的情况也需要花费大量的工作。我成功地只获得了第一点,而且只有Python。这让我想知道我是否采取了正确的方法?你对此有何看法......也许我不应该在我的库和抽象基类中使用Qt,而只使用纯C ++。它可能会让事情变得更容易一些。或者也许我应该只在我的库中使用C,并使插件返回一个C结构而不是一个类。我相信这会使事情变得更容易,因为调用图书馆将是一件微不足道的事情。我相信实现C ++类会更容易实现C结构,甚至更容易实现使用Qt对象的C ++类。
请指出正确的方向,并分享您的专业知识。此外,如果您知道有关该主题的任何书籍,我将非常乐意购买它。或者某些处理此问题的链接会这样做。
答案 0 :(得分:1)
C ++破坏了它的符号,并且具有特殊的魔法来定义类,这些类在标准(C)目标文件之上被黑客攻击。您不希望其他语言的文件理解这种魔力。所以我肯定会按照你自己的建议,用纯粹的C做一切。
但是,这并不意味着你不能使用C ++。只有接口必须是C,而不是实现。或者更严格地说,生成的目标文件不得使用其他语言不使用的特殊功能。
虽然插件可以链接到你的程序并因此使用它的功能,但我个人觉得在加载后调用插件函数更可读(因此可维护),传递一个函数指针数组,它可以被插件使用。
每种语言都支持打开共享对象(SO或DLL)文件。使用它。
您的界面将包含具有多个参数和返回类型的函数,这些函数可能对传入或检索它们的方式有特殊需求。可能有自动化系统,但我个人只是手工编写接口文件。最重要的是你正确地记录了界面,因此人们可以使用他们想要的任何语言,只要他们知道如何从他们的语言加载目标文件。
不同的语言有非常不同的存储对象的方式。我建议让数据的创建者也是内存的拥有者。因此,如果您的程序有一个带有构造函数的类(它包含在插件接口的C函数中),那么该类就是创建数据的类,而您的程序(而不是插件)应该拥有它。这意味着插件需要在完成后通知您的程序,此时程序可以销毁它(当然,除非它仍然需要)。在支持它的语言中,例如Python和C ++,这可以在它们的接口对象被销毁时自动完成。 (我在这里假设插件将创建一个对象以便与实际对象进行通信;此对象的行为类似于真实对象,但是使用目标语言而不是C。)
将任何库(例如Qt)保留在接口之外。您可以允许“将资源#x放在屏幕上的此位置”等功能,但不允许“将此Qt对象放在屏幕上的此位置”。原因是当你需要插件传递Qt对象时,他们需要理解Qt,这使得编写插件变得更加困难。
如果插件完全受信任,您可以允许它们将(不透明)指针传递给这些对象,但是对于与使用其他数字类型没有任何区别的接口。除了在程序中调用函数之外,不要求他们对对象做任何事情。