如何通过静态库(macOS)在主进程和动态库之间共享全局变量?
我的问题似乎与此问题类似,但在我的情况下,共享变量位于静态库中,并且此问题的建议对我没有帮助:。一路上,我看到了这个问题的问题,但也没有最终的解决办法: 我试图使我的主进程和一个动态库如何通过静态库(macOS)在主进程和动态库之间共享全局变量?,c,linker,dynamic-library,C,Linker,Dynamic Library,我的问题似乎与此问题类似,但在我的情况下,共享变量位于静态库中,并且此问题的建议对我没有帮助:。一路上,我看到了这个问题的问题,但也没有最终的解决办法: 我试图使我的主进程和一个动态库dlopen共享全局变量SHARED,该变量位于它们都链接到的共享库中 我已经创建了一个项目,但我也提供了该项目的内容如下 问题:我期望的输出是在这两种情况下看到相同的变量和相同的地址。相反,我看到的是SHARED变量的两个副本 我的问题:编译和链接器标志的哪种组合可以删除SHARED变量的第二个实例,以便在主进程
dlopen
共享全局变量SHARED
,该变量位于它们都链接到的共享库中
我已经创建了一个项目,但我也提供了该项目的内容如下
问题:我期望的输出是在这两种情况下看到相同的变量和相同的地址。相反,我看到的是SHARED
变量的两个副本
我的问题:编译和链接器标志的哪种组合可以删除SHARED
变量的第二个实例,以便在主进程和动态库之间只正确共享一个实例
附加背景
经过进一步研究,我认为这个问题可以简化为以下问题:如何获得-rdynamic
标志的Linux行为
我不打算这样运行代码。我正在移植在Linux上运行的现有软件。该软件在其主进程和动态库之间共享全局变量。我已经验证了它正在使用-rdynamic
在Linux上实现这种行为:在Linux上,只需将-rdynamic
添加到示例可执行文件的链接器标志中即可!使全局变量成为共享变量
描述我正在查找的行为:
如果使用“dlopen”加载需要引用程序定义的符号的动态对象,而不是其他动态对象,则在链接程序本身时可能需要使用此选项
现在的问题是,我无法用macOS上的示例实现这种行为。添加-rdynamic
似乎没有在Linux上产生的效果
输出
Hello, World!
SHARED: 0x104970030 123
SHARED: 0x104988018 (null)
Process finished with exit code 0
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)
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;
}
#include "dynamic_lib.h"
#include "static_lib.h"
#include <stdio.h>
void dynamic_lib_func() {
printf("SHARED: %p %s\n", &SHARED, SHARED);
}
#include "static_lib.h"
char *SHARED; // adding = 0 doesn't change much
CMakeLists.txt
Hello, World!
SHARED: 0x104970030 123
SHARED: 0x104988018 (null)
Process finished with exit code 0
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)
主可执行文件和
static_lib.c
中的动态库链接。因此,您将有两个char*共享的实例代码>。如果动态库中的函数将使用它们自己的实例,或者将该实例用于主可执行文件,我想这取决于实现。在您的情况下,它看起来好像使用了自己的
解决方案是删除char*SHARED从主可执行文件执行代码>并在dlopen
之后执行此操作:
char **shared = dlsym(handle, "SHARED");
if (!shared)
{
perror("dlsym failed");
exit(EXIT_FAILURE);
}
*shared = "123";
我的dlopen
和dlsym
内存有点生锈,因此代码可能包含一些小错误
补充意见
不要使用assert
测试dlopen
和dlsym
的返回值<代码>断言
用于检测代码中的逻辑错误。不建议将其用于检测其他运行时错误。根据您的工具链和设置,它甚至可能是一个noop
不要使用全局变量与库函数通信。函数需要知道的所有信息都应该可以通过函数参数访问 做了更多的实验,调整了链接器标志,这让我想到了其他一些SO问题,包括和
这不是在Linux上工作的-rdynamic
,而是在macOS上工作的:
必须将-未定义的动态\u查找添加到动态库的链接器标志中
在我的示例中,更改如下:
# It is important that we DO NOT link against static_lib and at the same time
# the -undefined dynamic_lookup is provided.
# target_link_libraries(dynamic_lib static_lib)
target_link_options(dynamic_lib PRIVATE -undefined dynamic_lookup)
我现在看到的输出是:
Hello, World!
SHARED: 0x109ead030 123
SHARED: 0x109ead030 123
Process finished with exit code 0
谢谢你的回答。我花了一些时间去我的Linux机器上检查我的示例在Linux上是如何工作的。在Linux上,只需添加-rdynamic
即可使全局变量成为共享变量。请再次查看我的问题:我在那里添加了其他信息。