Мой вопрос, похоже, похож на этот вопрос, однако в моем случае общая переменная находится в stati c библиотеке, а также советы из этого вопроса мне не помогли: Обмен глобальными данными между общей библиотекой и основной . По пути я видел проблемы из этого вопроса, но также не нашел окончательного решения: компоновщик OS X не смог найти символы из файла C, который содержит только переменные .
Я пытаюсь создайте мой основной процесс и динамическую c библиотеку, чтобы она dlopen
разделяла глобальную переменную SHARED
, расположенную в общей библиотеке, на которую они оба ссылаются.
Я создал минимальный проект на GitHub , но я также предоставляю содержание этого проекта ниже.
Проблема: Вывод, который я ожидаю, состоит в том, чтобы увидеть одну и ту же переменную и один и тот же адрес в обоих случаях. Вместо этого я вижу две копии переменной SHARED
.
Мой вопрос: какая комбинация флагов компиляции и компоновщика могла бы удалить второй экземпляр переменной SHARED
, чтобы только один экземпляр был должным образом распределен между основным процессом и динамикой c library.
Дополнительный фон
После дополнительных исследований, я думаю, этот вопрос можно свести к следующему: как получить поведение Linux -rdynamic
flag?
Я не собираюсь запускать подобный код. Я портирую существующее программное обеспечение, которое работает на Linux. Это программное обеспечение разделяет глобальные переменные между его основным процессом и динамическими библиотеками c. Я убедился, что он использует -rdynamic
для достижения такого поведения на Linux: на Linux, просто добавив -rdynamic
к флагам компоновщика исполняемого файла моего примера! сделать глобальную переменную доступной для общего доступа.
Что именно делает -rdynamic
и когда именно это необходимо? описывает поведение, которое я ищу:
Если вы используете «dlopen» для загрузки динамического c объекта, который должен ссылаться на символы, определенные программой, а не на какой-либо другой динамический c объект, то вам, вероятно, понадобится использовать эту опцию при компоновке Сама программа. ...
Теперь проблема в том, что я не могу добиться такого поведения с моим примером на macOS. Добавление -rdynamic
, кажется, не имеет эффекта, который он имеет на Linux.
output
Hello, World!
SHARED: 0x104970030 123
SHARED: 0x104988018 (null)
Process finished with exit code 0
main. c
#include "dynamic_lib.h"
#include <assert.h>
#include <dlfcn.h>
#include <stdio.h>
extern char *SHARED;
int main() {
printf("Hello, World!\n");
SHARED = "123";
printf("SHARED: %p %s\n", &SHARED, SHARED);
void *handle = dlopen("libdynamic_lib.dylib", RTLD_NOW | RTLD_GLOBAL);
assert(handle != NULL);
void *sym = dlsym(handle, "dynamic_lib_func");
assert(sym != NULL);
((void (*)(void))sym)();
return 0;
}
dynamic_lib. c
#include "dynamic_lib.h"
#include "static_lib.h"
#include <stdio.h>
void dynamic_lib_func() {
printf("SHARED: %p %s\n", &SHARED, SHARED);
}
static_lib. c
#include "static_lib.h"
char *SHARED; // adding = 0 doesn't change much
CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
project(untitled1 C)
set(CMAKE_C_STANDARD 99)
add_library(static_lib STATIC static_lib.c)
add_library(dynamic_lib SHARED dynamic_lib.c)
target_link_libraries(dynamic_lib static_lib)
add_executable(untitled1 main.c)
target_link_libraries(untitled1 static_lib)
add_dependencies(untitled1 dynamic_lib)