Загрузка расширенной библиотеки с помощью Python - PullRequest
0 голосов
/ 10 июля 2020

Я пытаюсь связать разделяемую библиотеку с помощью механизма ctypes в Python. Это хорошо работает с обычными библиотеками, но теперь мне приходится иметь дело с библиотекой, которая расширяет свои собственные функции с помощью набора плагинов. Когда я загружаю эту библиотеку, используя

import ctypes
lib = ctypes.cdll.LoadLibrary('./liblibrary.so')

, она сначала инициализирует все найденные плагины. И в этой ситуации плагины пытаются получить доступ к символам в liblibrary.so, которые не найдены. Если я использую его из программы C и связываю liblibrary как обычный общий объект, все работает как шарм. liblibrary.so связан с включенным флагом --export-dynmaic.

Вот минимальный рабочий пример: liblibrary. c:

#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>


typedef int (*func_t)(int);

static int verbosity = 0;
static func_t worker;

    __attribute__((constructor))
void lib_init()
{
    void * handle;

    dlerror();
    handle = dlopen("./plugin.so", RTLD_NOW);
    if (!handle) {
        fprintf(stderr, "error open: %s\n", dlerror());
        abort();
    }

    dlerror();
    worker = (func_t) dlsym(handle, "worker_function");
    if (!worker) {
        fprintf(stderr, "error dlsym: %s\n", dlerror());
        abort();
    }

}


int lib_getverbosity()
{
    return verbosity;
}

void lib_setverbosity( int _v )
{
    verbosity = _v;
}


int lib_work(int v)
{
    return worker(v);
}

Вот пример плагина:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

extern int lib_getverbosity();
extern int lib_setverbosity(int v);

int worker_function(int v)
{
    int verb = lib_getverbosity();
    printf("verbosity (plugin) : %d \n", v);
    return v * v;
}


и Makefile:

all: liblibrary.so plugin.so


liblibrary.so: liblibrary.c
    gcc -shared -O2 -fPIC -g -rdynamic -Wl,--export-dynamic liblibrary.c -o liblibrary.so

plugin.so:
    gcc -shared -O2 -fPIC -g -rdynamic -Wl,--export-dynamic plugin.c -o plugin.so

clean:
    rm *.so

.PHONY: clean

Теперь, когда я запускаю код Python, я получаю:

>>> import ctypes
>>> ctypes.cdll.LoadLibrary('./liblibrary.so')
error open: ./plugin.so: undefined symbol: lib_getverbosity

Почему это происходит и как могу ли я предотвратить это?

Удаление автоматической инициализации или превращение ее в функцию, которая должна быть вызвана пользователем, не является вариантом, поскольку в моем приложении это сломает очень старый API / ABI .

Если посмотреть глубже в liblibrary.so с помощью readelf, вы увидите:

readelf --dyn-syms library.so 

Symbol table '.dynsym' contains 15 entries:
   Num:    Wert           Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND dlopen
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND abort@GLIBC_2.2.5 (2)
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTab
     4: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     5: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND dlerror
     6: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND dlsym
     7: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __fprintf_chk@GLIBC_2.3.4 (3)
     8: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
     9: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@GLIBC_2.2.5 (2)
    10: 0000000000000000     0 OBJECT  GLOBAL DEFAULT  UND stderr@GLIBC_2.2.5 (2)
    11: 0000000000001230    11 FUNC    GLOBAL DEFAULT   14 lib_setverbosity
    12: 00000000000010e0   128 FUNC    GLOBAL DEFAULT   14 lib_init
    13: 0000000000001240    10 FUNC    GLOBAL DEFAULT   14 lib_work
    14: 0000000000001220    11 FUNC    GLOBAL DEFAULT   14 lib_getverbosity

Что выглядит нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...