QLibrary - import a class

女生的网名这么多〃 提交于 2019-12-19 07:42:32

问题


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

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.

This is the example I made.

This is the class declaration:

class TESTDLL_LIBSHARED_EXPORT TestDLL_lib
{

public:
    TestDLL_lib();

    int a;
    int b;
    int c;

    int getValues();
}; 

and this the implementation:

#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();
    }
}

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?

Thank you..


回答1:


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:

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.

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();
}


来源:https://stackoverflow.com/questions/26234327/qlibrary-import-a-class

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!