Динамическая компиляция общей библиотеки с помощью g++
Я пытаюсь скомпилировать следующий простой пример кода библиотеки DL из программа-библиотека-HOWTO С g++. Это просто пример, чтобы я мог научиться использовать и писать общие библиотеки. Реальный код для библиотеки, которую я разрабатываю, будет написан на C++.
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
int main(int argc, char **argv) {
void *handle;
double (*cosine)(double);
char *error;
handle = dlopen ("/lib/libm.so.6", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
cosine = dlsym(handle, "cos");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
printf ("%fn", (*cosine)(2.0));
dlclose(handle);
}
если я компилирую программу с gcc, она работает нормально.
gcc -o foo foo.c -ldl
когда я изменяю имя файла и компилятор на следующий
g++ -o foo foo.cpp -ldl
Я получаю следующее ошибка:
фу.cpp: 16: ошибка: недопустимое преобразование из "void*" в " double (*)(double)"
Я понимаю (я думаю я понимаю, поправьте меня, если это неправильно) , что я не могу сделать неявное приведение из Указателя void в C++, но C позволяет мне, и поэтому приведенный выше код будет компилироваться с помощью gcc, но не с помощью g++. Поэтому я попробовал явный бросок, изменив строку 16 выше на:
cosine = (double *)dlsym(handle, "cos");
С этим на месте, я получаю следующее ошибка:
фу.cpp: 16: ошибка: не удается преобразовать "double*" в "double (*) (double)" в присваивании
эти проблемы, вероятно, больше связаны с моим общим незнанием надлежащих стандартов кодирования c++, чем что-либо еще. Может ли кто-нибудь указать мне хороший учебник по разработке динамических библиотек для Linux, использующих пример кода C++?
3 ответов
C допускает неявные преобразования от void *
для любого типа указателя (включая указатели функций); C++ требует явного приведения. Как говорит лейфлундгрен, вам нужно привести возвращаемое значение dlsym()
к типу указателя функции, который вам нужен.
многие люди находят синтаксис указателя функции C неудобным. Одним из распространенных шаблонов является typedef указатель функции:
typedef double (*cosine_func_ptr)(double);
вы можете определить переменную указателя функции cosine
как член вашего тип:
cosine_func_ptr cosine;
и приведение с использованием типа вместо неудобного синтаксиса указателя функции:
cosine = (cosine_func_ptr)dlsym(handle, "cos");
dlsym
возвращает указатель на символ. (As void*
быть общим.)
В вашем случае вы должны привести его к функции-указателю.
double (*mycosine)(double); // declare function pointer
mycosine = (double (*)(double)) dlsym(handle, "cos"); // cast to function pointer and assign
double one = mycosine(0.0); // cos(0)
Итак, это один из тех редких случаев, когда ошибка компилятора является хорошей подсказкой. ;)
С тем, как ваш код, если он написан, это действительно больше вопрос C, но вы можете заставить это работать на C++. У меня нет учебника для вас по динамическим общим библиотекам (веб-страница, на которую вы ссылаетесь, кажется прекрасной), но вот как исправить ваш код на C++:
-
объявите my_cos функцией, которая (в конечном итоге) вызовет динамически загруженную косинусную функцию:
double my_cos(double);
-
присвоить указатель на функцию с my_cos
my_cos = (double (*)(double)) dlsym(handle, "cos");
Это немного сложно, но он назначает my_cos что-то, что возвращает double, является результатом разыменования другого указателя функции и принимает double в качестве аргумента. Как и другие люди, c++ немного более требователен к эксплицитности вашего кода, чем C.
-
замените это довольно датированное сообщение fputs на std:: cerr или std:: cout:
std::cerr << "error loading library cos: " << error << std::endl;
и
std::cout << "result is " << (*my_cos)(2.0)) << std::endl;
надеюсь, что это поможет. Если эта странная касти пугает вас, я бы рекомендовал Deep C Secrets Ван Линдена и, безусловно, книгу Кернигана и Ричи о C.
Edit: хороший момент в комментарии о том, как вы специально ищете руководство по разработке на C++, а не C, чтобы избежать этого типа проблемы. Я не знаю сопоставимого руководства на C++, но около 99% кода C может быть встроено в C++ код и работа просто отлично. Этот случай указателя функции является одним из исключений.