Как dlsym загрузить функцию QString

Я пытаюсь написать инструмент C++, используя Qt для системы Linux. мой инструмент, использующий общую библиотеку. Я пишу библиотеку для передачи данных в базу данных. такой метод в заголовочном файле

QString pushdata(QVariantMap params);

этот fucion поместил в lib call libpushdata.so. Я хотел бы загрузить динамическую библиотеку, поэтому я использую dlfcn.h и такой метод:

void *handle;
QString (*pushdata)(QVariantMap*);
handle = dlopen("libpushdata.so", RTLD_LAZY);
if (!handle) {
    fputs(dlerror(), stderr);
    exit(1);
}
pushdata=dlsym(handle,"pushdata");

при сборке программы получаю ошибку:

недопустимое преобразование из 'void*' в 'QString ()(QVariantMap)

Я ищу в Google, как использовать библиотеку динамической загрузки, и получаю такую ​​инструкцию здесь и здесь любой может показать мне, как загрузить мой метод QString pushdata(QVariantMap params) в общую библиотеку. Я использую Eclipse и Centos 6.5, Qt4.8


person Trương Hồng Quyền    schedule 14.01.2015    source источник


Ответы (2)


Вы можете использовать QLibrary для динамического вызова функций. Следующий пример вызывает функцию из разделяемой библиотеки во время выполнения:

#include <QLibrary>
#include <QDebug>

typedef QString (*call_func)(QVariantMap* arg1);

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QLibrary library( "dynamic_library" );
    library.load();
    if( !library.isLoaded() )
    {
        qDebug() << "Cannot load library.";
        return 0;
    }
    call_func func = (call_func)library.resolve( "pushdata" );
    if(func)
    {
        func(variantMap);
    }

    return a.exec();
}
person Nejat    schedule 14.01.2015
comment
спасибо @Nejat, я попробую ваш метод и все равно получаю ошибку error while loading shared libraries: liblibtest.so: cannot open shared object file: No such file or directory - person Trương Hồng Quyền; 14.01.2015
comment
Вы размещаете файл so рядом с исполняемым файлом? - person Nejat; 14.01.2015
comment
Вы связываете библиотеку с вашим приложением? Или вы хотите загрузить его динамически? - person Nejat; 14.01.2015
comment
я также связываю свое приложение с библиотекой, но все равно ошибка. когда я перехожу в каталог, содержащий приложение, и использую приложение exprot LD_LIBRARY_PATH=/root/Desktop/loaddl/Debug и ./application, работающее нормально, папка Debug содержит lib.so @@. Так что вы можете сказать мне, как запустить приложение без использования exprot LD_LIBRARY_PATH использовать только ./application для запуска - person Trương Hồng Quyền; 14.01.2015
comment
Если вы хотите динамически загружать библиотеку во время выполнения, зачем вы связываете ее со своим приложением? Нет необходимости связываться, если вы хотите загружать динамически. - person Nejat; 14.01.2015
comment
Если вы хотите связать библиотеку со своим приложением, то нет необходимости использовать QLibrary. Вы можете просто включить заголовочный файл и использовать классы. В этом случае просто поместите файл so рядом с исполняемым файлом и добавьте несколько строк в ваш файл pro, чтобы динамический компоновщик искал в том же каталоге, что и приложение, см.: stackoverflow.com/questions/23896643/ - person Nejat; 14.01.2015
comment
спасибо @Nejat, я использую ваш пример и удаляю ссылку на приложение, и все работает нормально - person Trương Hồng Quyền; 14.01.2015

Вы можете использовать механизм плагинов Qt, как ответил Nejat.

Если вы настаиваете на использовании только dlopen(3) и dlsym заботиться о:

  • передача полного пути к общей библиотеке (например, dlopen("./foo.so", RTLD_NOW), а не только dlopen("foo.so" ...) ...) и всегда проверять успешность dlopen
  • остерегайтесь изменения имен, поэтому объявите функцию dlsymed как extern "C" в вашем плагине.
  • явное приведение результирующего указателя:

    typedef QString pushdata_sig_t(QVariantMap*);
    pushdata_sig_t* pushdata 
      = reinterpret_cast<pushdata_sig_t*>(dlsym(handle,"pushdata"));
    if (!pushdata) 
      { std::cerr << "dlsym failed:" << dlerror ()
                  << std::endl; 
        exit(EXIT_FAILURE); }
    

Прочитайте хотя бы C++ dlopen mini Howto.

person Basile Starynkevitch    schedule 14.01.2015