Я создаю общую библиотеку на C, которая динамически загружается программой, к которой у меня нет доступа к исходному коду. Целевой платформой является 64-битная платформа Linux, и мы используем gcc для сборки. Мне удалось воспроизвести выпуск примерно в 100 строк, но это все еще немного для чтения. Надеюсь, это иллюстративно.
Основная проблема заключается в том, что у меня есть две нестатические функции (bar
и baz
), определенные в моей общей библиотеке. Оба должны быть нестатическими, так как мы ожидаем, что вызывающая сторона сможет их dlsym. Кроме того, baz
вызывает bar
. Программа, использующая мою библиотеку, также имеет функцию с именем bar
, которая обычно не вызывает проблем, но вызывающая программа скомпилирована с -rdynamic
, так как у нее есть функция foo
, которую нужно вызывать в моей общей библиотеке. В результате моя разделяемая библиотека оказывается связанной с версией bar
вызывающей программы во время выполнения, что приводит к неинтуитивным результатам.
В идеальном мире я мог бы включить некоторый переключатель командной строки при компиляции моей общей библиотеки, который предотвратил бы это.
Текущее решение, которое у меня есть, состоит в том, чтобы переименовать мои нестатические функции как funname_local
и объявить их статическими. Затем я определяю новую функцию: funname() { return funname_local(); }
и меняю все ссылки на funname
в моей общей библиотеке на funname_local
. Это работает, но кажется громоздким, и я бы предпочел просто сказать компоновщику, чтобы он предпочитал символы, определенные в локальной единице компиляции.
внутренний.c
#include <stdio.h>
#include "internal.h"
void
bar(void)
{
printf("I should only be callable from the main program\n");
}
внутр.ч
#if !defined(__INTERNAL__)
#define __INTERNAL__
void
bar(void);
#endif /* defined(__INTERNAL__) */
main.c
#include <dlfcn.h>
#include <stdio.h>
#include "internal.h"
void
foo(void)
{
printf("It's important that I am callable from both main and from any .so "
"that we dlopen, that's why we compile with -rdynamic\n");
}
int
main()
{
void *handle;
void (*fun1)(void);
void (*fun2)(void);
char *error;
if(NULL == (handle = dlopen("./shared.so", RTLD_NOW))) { /* Open library */
fprintf(stderr, "dlopen: %s\n", dlerror());
return 1;
}
dlerror(); /* Clear any existing error */
*(void **)(&fun1) = dlsym(handle, "baz"); /* Get function pointer */
if(NULL != (error = dlerror())) {
fprintf(stderr, "dlsym: %s\n", error);
dlclose(handle);
return 1;
}
*(void **)(&fun2) = dlsym(handle, "bar"); /* Get function pointer */
if(NULL != (error = dlerror())) {
fprintf(stderr, "dlsym: %s\n", error);
dlclose(handle);
return 1;
}
printf("main:\n");
foo();
bar();
fun1();
fun2();
dlclose(handle);
return 0;
}
main.h
#if !defined(__MAIN__)
#define __MAIN__
extern void
foo(void);
#endif /* defined(__MAIN__) */
общий.с
#include <stdio.h>
#include "main.h"
void
bar(void)
{
printf("bar:\n");
printf("It's important that I'm callable from a program that loads shared.so"
" as well as from other functions in shared.so\n");
}
void
baz(void)
{
printf("baz:\n");
foo();
bar();
return;
}
скомпилировать:
$ gcc -m64 -std=c89 -Wall -Wextra -Werror -pedantic -o main main.c internal.c -l dl -rdynamic
$ gcc -m64 -std=c89 -Wall -Wextra -Werror -pedantic -shared -fPIC -o shared.so shared.c
бежать:
$ ./main
main:
It's important that I am callable from both main and from any .so that we dlopen, that's why we compile with -rdynamic
I should only be callable from the main program
baz:
It's important that I am callable from both main and from any .so that we dlopen, that's why we compile with -rdynamic
I should only be callable from the main program
bar:
It's important that I'm callable from a program that loads shared.so as well as from other functions in shared.so
#define foo foo_internal
. Кстати, вы можете автоматизировать часть этого, возможно, настроив свой компилятор (например, с помощью GCC MELT....) - person Basile Starynkevitch   schedule 13.09.2016bar()
разделяемой библиотеки во что-то уникальное и указать основной программе искать его по этому имени (например, какому-то конфигурации программы)? - person John Bollinger   schedule 13.09.2016