Динамическая загрузка файла .so и ссылка на символы

Я разрабатываю приложение Linux C ++, которое использует драйвер приложения. Разработчик оборудования предоставляет SDK (включает и библиотеки). Я хочу использовать библиотеки динамически через dlopen (), чтобы приложение работало без драйвера (или, возможно, с другим драйвером).

Когда я использовал метод из одной из библиотек таким образом:

int (*VCI_OpenCAN)(PVCI_CAN_PARAM) = (int(*)(PVCI_CAN_PARAM))dlsym(_driver_library, "VCI_OpenCAN");

        int open_code = VCI_OpenCAN(&vcparam);

        if ( 0 == open_code) {
            qDebug() << "ERROR: " << open_code;
            exit(1);
        }

Он сказал мне, что есть неразрешенный символ Open_Com. Хорошо, вероятно, он вызывается внутри VCI_OpenCAN, но nm сообщает, что в библиотеке (например, lib1.so) есть U (неопределенный) символ Open_Com. Я покопался и нашел Open_Com в другой библиотеке (lib2.so) в комплекте SDK.

Итак, вопрос: как я могу (и возможно ли это?) Включить динамическую загрузку обеих библиотек и заставить их видеть символы друг от друга, или единственное решение - статическая компоновка? Статическая компоновка работает, в связанном примере используется

$(CC) $(CFLAGS) $(LDFLAGS) -o $@ i7565H1H2.o ../lib/libI7565H1H2_64.so.1.0 ../lib/libi7k_64.so.1.0 $(AM_LDFLAGS)```

person Kirill Sarksyan    schedule 03.09.2020    source источник
comment
Первая библиотека должна была быть связана со второй библиотекой. Он построен неправильно, и вам, по-видимому, предоставляется возможность связываться с обеими библиотеками. Плохой дизайн. Также можно вручную открыть вторую библиотеку с флагом RTLD_GLOBAL.   -  person Sam Varshavchik    schedule 03.09.2020
comment
Предоставленный lib1.so должен явно зависеть от lib2.so (см. Строки NEEDS в выходных данных readelf -d). Если поставщик не может исправить это, сначала загрузите lib2.so, а затем lib1.so.   -  person Lorinczy Zsigmond    schedule 03.09.2020
comment
@SamVarshavchik большое спасибо, вроде работает :)   -  person Kirill Sarksyan    schedule 03.09.2020


Ответы (1)


Также вручную откройте вторую библиотеку с флагом RTLD_GLOBAL.

_i7k_library = dlopen("/home/kkursor/tmp/libi7k_64.so.1.0", RTLD_GLOBAL | RTLD_NOW);
_driver_library = dlopen(config.value(section + "/driver_library").toString().toLocal8Bit(), RTLD_LAZY);
person Kirill Sarksyan    schedule 03.09.2020