std :: function из dlsym приводит к ошибке сегментации - PullRequest
0 голосов
/ 18 мая 2018

Я хочу динамически связать разделяемую библиотеку и назначить ей функцию для std::function.Вот код:

function.cpp:

#include <array>

#ifdef __cplusplus
extern "C" {
#endif

double function(std::array<double, 1> arg)
{
    return arg[0] * 2;
}

#ifdef __cplusplus
}
#endif

main.cpp:

#include <functional>
#include <iostream>
#include <fstream>
#include <array>
#include <functional>

#ifdef __linux__
#include <dlfcn.h>
#endif

int main()
{
void *handle;
double (*function)(std::array<double, 1>);
char *error;

handle = dlopen("/home/oleg/MyProjects/shared_library_test/libFunction.so", RTLD_LAZY);
if (!handle) 
{
    fprintf(stderr, "%s\n", dlerror());
    exit(EXIT_FAILURE);
}

dlerror();
*(void **) (&function) = dlsym(handle, "function");

if ((error = dlerror()) != NULL)
{
    fprintf(stderr, "%s\n", error);
    exit(EXIT_FAILURE);
}

std::cout << "Native function output: " << function(std::array<double, 1>{ 3.0 }) << std::endl;
dlclose(handle);

std::function<double(std::array<double, 1>)> std_function(*function);
std::cout << "std::function output: " <<  std_function(std::array<double, 1>{ 3.0 }) << std::endl;

exit(EXIT_SUCCESS);
}

Сборкаобщая библиотека:

g++ -Wall -Wextra -g -std=c++17 -shared -o libFunction.so -fPIC function.cpp

Основная сборка:

g++ -Wall -Wextra -g -std=c++17 main.cpp -ldl

Запуск программы приводит к следующему выводу:

Native function output: 6
Segmentation fault

Итак, как вы можете видеть, яуспешно скомпилировать библиотеку и загрузить ее в мою основную программу.Однако назначение указателя функции на std::function не работает.

Пожалуйста, помогите!

1 Ответ

0 голосов
/ 18 мая 2018

Вам лучше выполнить преобразование в стиле C ++:

using func_ptr = double (*)(std::array<double, 1>);
func_ptr function = reiterpret_cast<func_ptr>( dlsym(handle, "function") );

Но виновником является то, что вы не можете вызвать эту функцию прямо или косвенно через std::function обертку после закрытия разделяемой библиотеки:

dlclose(handle);
// function cannot be used anymore

обратите внимание, что для этого может быть лучше использовать RAII:

std::unique_ptr<void *,int(void*)> handle( dlopen("/home/oleg/MyProjects/shared_library_test/libFunction.so", RTLD_LAZY), dlclose );

, тогда вам не нужно вызывать dlclose() вручную

Примечание: плохая идея вызывать exitс main() в C ++, используйте return, подробности можно найти здесь Будет ли exit () или исключение препятствовать вызову деструктора конца области действия?

...