QLibrary-导入课程 [英] QLibrary - import a class

查看:49
本文介绍了QLibrary-导入课程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个QT库,我想将其导入另一个项目中.

I have a QT library and I want to import it in another project.

现在,由于我希望这样做,即使在修改库时,也不需要再次编译另一个项目,所以我开始使用QLibrary.

Now, since I want that, even when I modify the library, the other project does not need to be compiled again, I started using QLibrary.

但是...我无法导入课程.或者更好的是,我可以导入该类,但是无法访问其方法.

But... I can't import a class. Or better, I can import the class, but I can't access its methods.

这是我做的例子.

这是类声明:

class TESTDLL_LIBSHARED_EXPORT TestDLL_lib
{

public:
    TestDLL_lib();

    int a;
    int b;
    int c;

    int getValues();
}; 

,这是实现:

#include "testdll_lib.h"

TestDLL_lib::TestDLL_lib()
{
    a = 10;
    b = 20;
    c = 30;
}

int TestDLL_lib::getValues()
{
    return a+b+c;
}

extern "C" TESTDLL_LIBSHARED_EXPORT TestDLL_lib* create_TestDLL_lib()
{
   return new TestDLL_lib();
}

这是主文件,在另一个项目中:

while this is the main file, in the other project:

#include <testdll_lib.h>
#include <QDebug>
#include <QLibrary>

int main(int argc, char *argv[])
{
    QLibrary library("TestDLL_lib");
    if (library.load())
    {
        typedef TestDLL_lib* (*create_TestDLL_lib_fun)();
        create_TestDLL_lib_fun create_TestDLL_lib = (create_TestDLL_lib_fun)library.resolve("create_TestDLL_lib");

        if (create_TestDLL_lib)
        {
            TestDLL_lib *myClassInstance = create_TestDLL_lib();

            if (myClassInstance)
            {
                //qDebug() << QString::number(myClassInstance->getValues());
                qDebug() << QString::number(myClassInstance->a) + " " + QString::number(myClassInstance->b) + " " + QString::number(myClassInstance->c);
            }
        }

        library.unload();
    }
}

现在,我可以访问对象 myClassInstance a b c )>(而且,如果我在DLL中更改它们,它们也将在程序中更改而无需重建),但是我不能调用 myClassInstance-> getValues(),因为我得到了

Now, I can access all the data values (a, b, c) of the object myClassInstance (and, if i change them in the DLL, they also get changed in the program without a rebuild) but I can't call myClassInstance->getValues() because I get

main.obj:-1: error: LNK2001: unresolved external symbol "__declspec(dllimport) public: int __thiscall TestDLL_lib::getValues(void)" (__imp_?getValues@TestDLL_lib@@QAEHXZ)

我该如何解决?是否可以从导入的类中调用方法?

How can I solve this? Is it possible to call methods from imported classes?

谢谢..

推荐答案

您不能在运行时导入的类上调用方法.这是因为编译器在编译时而不是在运行时链接了这些调用(它不能这样做).我们的好朋友vtable提供了一条出路:

You cannot call methods on classes imported at runtime. This is because the compiler links these calls at compile-time and not at run-time (which it cannot do). A way out is provided by our good ol' friend, the vtable:

您可以在实现接口的类上调用 virtual 方法(该接口在运行时未导入").这意味着使用 virtual (可能是纯虚拟)方法定义一个定义接口的类.然后, TestDLL_lib 将继承该接口,并实现这些方法.您将通过该接口引用 TestDLL_lib 实例,并通过该接口调用方法,从而通过接口的vtable有效地调用它们,该接口的vtable被 TestDLL_lib 的vtable取代"

You can, call virtual methods on classes implementing an interface (the interface is not "imported" at runtime). That means to define a class defining the interface using virtual (possibly pure virtual) methods. TestDLL_lib would then inherit that interface, implementing the methods. You would refer to the TestDLL_lib instance via that interface and call methods trough that interface, effectively calling them trough the vtable of the interface, which is "superseded" by TestDLL_libs vtable.

别忘了将虚拟机设置为虚拟代码,并在界面中添加虚拟机代码.如果不这样做,则无法通过接口指针安全地删除实例.

Don't forget to make your d'tor virtual and to add a virtual dtor to the interface. If you don't do that you cannot safely delete instance trough the interface pointer.

我可能还会解释为什么您可以访问成员,但不能在导入的"类上调用函数.通过内存位置访问成员,并且内存位置仅由编译器定义.因此,编译器生成代码以访问成员,而无需引用任何类的符号(方法等).反过来,这导致没有链接依赖性.但是请注意,如果您更改类,例如,您将需要使用DLL重新编译DLL和应用程序.添加或删除成员,因为这会更改内存布局.

I might also explain why you can access members, but not call functions on "imported" classes. The members are accessed by memory location, and the memory location is solely defined by the compiler. Thus the compiler generates the code to access members without ever referring to any of the classes' symbols (methods and so on). This in turns leads to no linkage dependency. Note however that you would need to recompile both the DLL and the application using the DLL if you change the class, e.g. adding or removing a member, since that changes the memory layout.

class TestInterface
{
public:
    virtual ~TestInterface()
    {
    }

    virtual int getValues() = 0;
}

class TESTDLL_LIBSHARED_EXPORT TestDLL_lib : public TestInterface
{

public:
    TestDLL_lib();
    virtual ~TestDLL_lib();

    int a;
    int b;
    int c;

    int getValues() override; // MSVC may not support "override"
}; 

// return pointer to interface!
// TestDLL_lib can and should be completely hidden from the application
extern "C" TESTDLL_LIBSHARED_EXPORT TestInterface *create_TestDLL_lib()
{
    return new TestDLL_lib();
}

这篇关于QLibrary-导入课程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆