如何通过静态库(macOS)在主进程和动态库之间共享全局变量? [英] How to share a global variable between a main process and a dynamic library via a static library (macOS)?

查看:295
本文介绍了如何通过静态库(macOS)在主进程和动态库之间共享全局变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题似乎与此问题相似,但是在我的情况下,共享变量位于静态库中,并且该问题的建议也没有帮助我: OS X链接器无法从仅包含变量的C文件中找到符号.

我正在尝试使它的主进程和一个动态库成为共享所有全局变量SHARED的动态库,该全局变量位于它们都链接到的共享库中.

我创建了一个最小GitHub上的项目,但我还在下面提供了该项目的内容.

问题:我期望的输出是在两种情况下都看到相同的变量和相同的地址.相反,我看到了SHARED变量的两个副本.

我的问题:编译和链接器标志的哪种组合可以删除SHARED变量的第二个实例,以便在主进程和动态库之间只能正确共享一个实例. /p>

其他背景

经过进一步研究,我认为这个问题可以简化为以下问题:如何获得-rdynamic标志的Linux行为?

我不是要运行这样的代码.我正在移植在Linux上运行的现有软件.该软件在其主要过程和动态库之间共享全局变量.我已经验证了它正在Linux上使用-rdynamic来实现这种行为:在Linux上,只需将-rdynamic添加到示例示例可执行文件的链接器标记中即可!使全局变量成为共享变量.

-rdynamic的确切作用什么时候才需要?描述了我要寻找的行为:

如果使用"dlopen"加载需要引用程序定义的符号的动态对象,而不是其他某些动态对象,则在链接程序本身时可能需要使用此选项. ...

现在的问题是,在macOS上,我的示例无法实现此行为.添加-rdynamic似乎没有在Linux上产生的效果.

输出

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)

解决方案

进行更多的实验并调整链接器标志使我想到了其他一些SO问题,包括.

这是在macOS上起作用的,而不是在Linux上起作用的-rdynamic:

必须将-undefined dynamic_lookup添加到动态库的链接器标志中.

在我的示例中,更改如下:

# 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

My question seems to be similar to this question however in my case the shared variable is in a static library and also the advice from this question didn't help me: Sharing global data between a shared library and main. Along the way I saw the issues from this question but no final solution either: OS X linker unable to find symbols from a C file which only contains variables.

I am trying to make my main process and a dynamic library that it dlopen's to share the global variable SHARED which is located in a shared library that they both link to.

I have created a minimal project on GitHub but I am also providing the contents of that project below.

The issue: The output I am expecting is to see the same variable and the same address in both cases. Instead I am seeing two copies of the SHARED variable.

My question: which combination of compilation and linker flags could remove the second instance of the SHARED variable so that only one instance would be properly shared between the main process and the dynamic library.

Additional background

After additional research, I think this question can be reduced to the following one: how to get the Linux behavior of the -rdynamic flag?

This is not my intention to run the code like this. I am porting existing software that runs on Linux. That software shares global variables between its main process and the dynamic libraries. I have verified that it is using -rdynamic to achieve this kind of behavior on Linux: on Linux, simply adding -rdynamic to the linker flags of my example's executable does! make the global variable to become shared.

What exactly does -rdynamic do and when exactly is it needed? describes the behavior that I am looking for:

If you use "dlopen" to load a dynamic object which needs to refer back to the symbols defined by the program, rather than some other dynamic object, then you will probably need to use this option when linking the program itself. ...

Now the problem is that I cannot achieve this behavior with my example on macOS. Adding -rdynamic seems to not have the effect that it has on 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)

解决方案

Doing more experiments and tweaking the linker flags led me to some other SO questions, including this and this.

Instead of -rdynamic that works on Linux, this is what works on macOS:

The -undefined dynamic_lookup has to be added to the linker flags of the dynamic library.

In my example, the change is as follows:

# 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)

The output that I see now is:

Hello, World!
SHARED: 0x109ead030 123
SHARED: 0x109ead030 123

Process finished with exit code 0

这篇关于如何通过静态库(macOS)在主进程和动态库之间共享全局变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆