saide_a Ответов: 1

Доступ к функции-члену из файла so


У меня есть заголовок .so и заголовок, который имеет класс, все члены которого являются виртуальными
и я хочу использовать этот класс и его функции в своей основной работе

Я пытаюсь следовать, но это дает мне ошибку сегментации

У меня нет доступа к нему, поэтому я должен его изменить

Что я уже пробовал:

CLASS_NAME * i;
void * h = dlopen("./LIBNAME.so",RTLD_NOW);
i = (CLASS_NAME *)dlsym(h, "CLASS_NAME");

i->Create(1);//member function

Richard MacCutchan

Поскольку у вас есть как заголовочные, так и общие объектные файлы, почему бы просто не использовать обычную компиляцию и ссылку?

saide_a

для компиляции я использую эту команду в терминале linux:
тест g++ -o test.cpp -ЛПНП
что - то не так?

Richard MacCutchan

Вы также должны добавить библиотеку общих объектов, которую хотите использовать, вместо того, чтобы пытаться получить к ней динамический доступ.

saide_a

большое спасибо за ваш ответ,
Я также использовал команду таким образом
g++ -o testcan testcan.cpp -путь L/lib-lLIBNAME.so
но я получил эту ошибку :/usr/bin/ld: не могу найти-lLIBNAME.so
Я добавил путь к библиотеке таким образом :
экспорт LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/MyFirstProjects/
но я все равно получаю ту же ошибку

Richard MacCutchan

Попробуйте сделать это (обратите внимание на двоеточие перед этим LIBNAME.so):
g++ -o testcan testcan.cpp -L/lib path -l:LIBNAME.so

Видеть ld(1): GNU linker - Man-страница Linux[^] для получения полной информации о различных вариантах компоновщика.

saide_a

это работает , но поскольку все функции-члены в заголовке являются чисто виртуальными , это создает еще одну проблему.
эта ошибка
невозможно выделить объект абстрактного типа ‘Class_Name’
calss_name.h:Примечание: поскольку следующие виртуальные функции являются чистыми внутри ‘class_name’:(все функции-члены)

Я думаю, что заставляю использовать динамическое связывание

Richard MacCutchan

Вы не можете создать объект из класса, который имеет все чисто виртуальные методы. И насколько мне известно, вы не можете создать библиотеку из такого класса, поэтому я понятия не имею, что эта библиотека содержит.

Rick York

Это означает, что вы должны вывести класс из этого класса, прежде чем сможете создать его экземпляр, и вы должны предоставить реализации объявленных чистых виртуальных методов.

saide_a

с помощью этой команды я получил функцию return object
Нм -Д LIB.so
но теперь после получения объекта у которого нет нулевого значения
при каждом вызове функции я получаю ошибку сегментации.
не могли бы вы мне помочь, пожалуйста?

Richard MacCutchan

Нет, я не могу вам помочь, потому что понятия не имею, что должна содержать эта библиотека и как устроены ее классы. Вам необходимо обратиться за помощью к человеку или людям, которые создали эту библиотеку.

saide_a

спасибо за твои Джуды.
Моя проблема решена, я не использовал скобки в строке "i = geti()" .
CLASS_NAME * (geti)(void) = NULL;
ИМЯ_КЛАССА * я;
void * h = dlopen("./LIBNAME.so",RTLD_NOW);
geti = (CLASS_NAME* (*) ()) dlsym(h, "CLASS_NAME");
я = гетов();
i->Create(1);

1 Ответов

Рейтинг:
5

Jochen Arndt

Вы получите ошибку сегментации, когда i является NULL. Проверьте, была ли успешна загрузка библиотеки и получение символа:

CLASS_NAME * i = NULL;
void * h = dlopen("./LIBNAME.so",RTLD_NOW);
// Get error message string upon errors
char *err = dlerror();
if (!h)
{
    // Report error here.
}
else
{
    i = (CLASS_NAME *)dlsym(h, "CLASS_NAME");
    if ((err = dlerror()) != NULL)
    {
        // Report error here.
    }
    else if (i)
    {
        i->Create(1);
    }
}
Смотреть также dlopen(3) - Man-страница Linux[^].

Есть ли какая-то конкретная причина, по которой вы используете динамическую загрузку? Если нет, просто свяжите свое приложение с библиотекой.


saide_a

Я получаю ошибку ошибки сегментации даже если я не равен нулю

CPallini

5.

saide_a

не могли бы вы помочь мне связать мое приложение с библиотекой?, выше я поместил свою команду using.

Jochen Arndt

Тогда это может быть связано с тем, как класс реализован в библиотеке. Синтаксис из вашего примера требует, чтобы функция dlsym (), вызываемая с именем класса, возвращала только что выделенный экземпляр объекта.

Смотреть также Динамическая загрузка классов для C++ в Linux.

saide_a

Нет , он не имеет функции для возврата экземпляра :(

Jochen Arndt

При использовании опции-l (строчная буква L) префикс "lib" и расширение должны быть опущены, а библиотека должна иметь соответствующее имя.

Если имя библиотеки является libname.so, используйте один из них:
-lname
-l:libname.so
full_path_to_libname.так
где первые два требуют, чтобы библиотека находилась в одном из каталогов, в которых выполняется поиск библиотек (определяется параметром-L или переменной среды LD_LIBRARY_PATH для общих библиотек).

saide_a

если все функции заголовка являются чисто виртуальными , могу ли я использовать статическое связывание?

Jochen Arndt

Это не проблема, связанная со связыванием. Чистые виртуальные функции должны быть реализованы в производных классах.

Если все функции являются чисто виртуальными, и даже нет смысла помещать класс в библиотеку. Тогда единственным кодом, хранящимся в библиотеке, будут общие операции, если они предусмотрены (например, конструктор, деструктор, копирование, перемещение). Но такие могут быть также помещены в заголовочный файл; и они, как правило, с абстрактными классами.

saide_a

с помощью этой команды я получил функцию return object
Нм -Д LIB.so
но теперь после получения объекта у которого нет нулевого значения
при каждом вызове функции я получаю ошибку сегментации.
не могли бы вы мне помочь, пожалуйста?

Jochen Arndt

Чтобы получить справку, вы должны показать фактически используемый код и заголовочный файл.

Вы тем временем связали библиотеку и вывели свой класс?
Тогда нет необходимости использовать nm. Вся необходимая информация находится в заголовочном файле.

saide_a

спасибо за твои Джуды.
Моя проблема решена, я не использовал скобки в строке "i = geti()" .
CLASS_NAME * (geti)(void) = NULL;
ИМЯ_КЛАССА * я;
void * h = dlopen("./LIBNAME.so",RTLD_NOW);
geti = (CLASS_NAME* (*) ()) dlsym(h, "CLASS_NAME");
я = гетов();
i->Create(1);