Создание плагина Qt и использование не виртуальных функций - PullRequest
0 голосов
/ 23 декабря 2011

Прежде всего я использую VS 2008 и динамическую сборку Qt 4.7.0.

interface.h:

class PluginInterface
{

public:        
        virtual void foo() = 0;
};

Q_DECLARE_INTERFACE(PluginInterface, MY_PLUGIN_VERSION)

И у меня есть и класс, который реализует этот интерфейс:

myplugin.h

class MyPlugin: public QObject, public PluginInterface
{
public:
        Q_OBJECT
        Q_INTERFACES(PluginInterface)
        virtual void foo(); // this functions is implemented in cpp file.
        static QString goo(); // this function is also implemented in cpp file.
};

Поэтому, когда я использую этот плагин в другом проекте (MySpecialPlugin), который будет скомпилирован как библиотека динамических ссылок (фактически также реализация интерфейса плагина), я не могу вызватьMyPlugin::goo();

Заголовок «MyPlugin.h» видим для MySpecialPlugin.И госпожа VS2008 успешно скомпилировала проект.Но у меня есть ошибка на шаге ссылки LNK2001, неопределенная ссылка.Но при изменении static void goo(); на virtual void goo(); это работает.

Я использую макрос Q_EXPORT_PLUGIN2 для создания плагинов.

Что я делаю неправильно?Устанавливает ли Qt дополнительные требования по реализации интерфейсов плагинов?

1 Ответ

1 голос
/ 23 декабря 2011
  1. Прежде всего вам нужно экспортировать свой класс (в Windows это волшебно, как __declspec(dllexport) после ключевого слова класса при компиляции вашего «myplugin» и __declspec(dllimport) при компиляции кода с его использованием (в данном случае MySpecialPlugin). можно достичь с помощью простого определения. читать дальше

    #ifdef _WIN32
    #ifdef MYPLUGIN_COMPILE
    #define MYPLUGIN_EXPORT __declspec(dllexport)
    #else
    #define MYPLUGIN_EXPORT __declspec(dllimport)
    #endif
    #else
    #define MYPLUGIN_EXPORT
    #endif
    
    class MYPLUGIN_EXPORT MyPlugin
    {
         // implementation
    };
    

    И добавьте MYPLUGIN_COMPILE в секцию препроцессора MyPlugin

  2. Вам необходимо создать ссылку на экспортируемую библиотеку

Вызов статических и "обычных" методов отличается от вызова виртуальных методов ... статические и "нормальные" методы всегда находятся по определенному адресу, и ваш код должен знать, где он находится ... виртуальный вызов "проверяет" класс vtable при чем У вашего метода есть реализация, и вы получите этот адрес «динамически» из этой таблицы. Кроме того, для платформы win32 VC необходимо определить, что что-то «экспортировано» (открыто) для доступа извне dll. Таким образом, в основном, если вы хотите напрямую вызывать что-либо из MyPlugin (каждый член, который не является виртуальным, вызывается напрямую), вы должны экспортировать его на платформу Win32 VC. Обратите внимание, что вызов напрямую виртуального метода с MyPlugin :: foo () вызовет ту же ошибку

...