在共享库和main之间共享全局数据

Sharing global data between a shared library and main

本文关键字:共享 全局 数据 之间 main      更新时间:2023-10-16

我有一个名为global_count的变量,我想在共享库和程序的主要部分(以及最终的其他库,但目前我已经简化了测试用例)之间共享它。

给定globals.cpp中global_count的声明:

extern "C" {
  int* global_count;
}    

我们编译以创建一个全局.o文件:

gcc -c global.cpp

下面的shared.cpp将用于创建共享。所以:

#include <stdio.h>
#include "global.h"
extern "C" {

void init_global_count(int* xp) {
  printf("Initialize global count to: %dn", *xp);
  global_count = xp;  
};
void print_global_count(){  
  if(global_count) {
    printf("global_count is: %dn",*global_count);   
  } else {
    printf("global_count* is not initialized!n");
  }
};
}

global.h:

extern "C" {
extern int* global_count;
}

main.cpp:

#include <stdlib.h>
#include <dlfcn.h>
#include <stdio.h>
#include "global.h"
int answer = 42;
int* gc_copy;
typedef void (*func)();
void (*init_global_count)(int*);
void (*print_global_count)();
void load(char* shared_lib){
  void* handle;  
  handle = dlopen(shared_lib,RTLD_NOW | RTLD_GLOBAL) ;
  printf("load:after dlopenn");
  if(!handle)
  {
    printf("DID NOT LOAD!n");
    fflush(stdout);
    fputs (dlerror(), stderr);
    exit(1);
  } else {
    printf("Loaded OK!n");
    fflush(stdout);
    void (*init_global_count)(int*) = (void (*)(int*))dlsym(handle, "init_global_count"); 
    (*init_global_count)(&answer);
    void (*print_global_count)() = (void (*)())dlsym(handle, "print_global_count");
    (*print_global_count)();
  }
}
int main(){
  printf("main...n");
  load((char*)"./shared.so");
  if(global_count)
    printf("main:global_count is: %dn", *global_count);
  return 0;
}

编译共享的lib和main:

gcc -g -Wall -fno-omit-frame-pointer -fPIC -shared -o shared.so shared.cpp global.o
gcc -g -o main main.cpp global.o -ldl

请注意,我们在global.o中链接了这两个汇编。

现在我们运行它,输出是:

main...
load:after dlopen
Loaded OK!
Initialize global count to: 42
global_count is: 42

因此,从*print_global_count()*内部报告的*global_count*(在shared.cpp中定义)如预期的那样为42。但是,global_count不是从main报告的,因为global_count指针尚未初始化-因此main.cpp中的global_count与shared.cpp中的global_count不同。

我想知道是否可以做我在这里尝试做的事情(在.so和加载.so的模块之间共享一些全局数据)?如果是,我是否需要以不同的方式链接?

共享库中的所有对象都需要编译为与位置无关的对象(-fpic-fPIC)。因此,在globals.o中链接到共享库是错误的。

实际上,您正在创建global_count指针的两个实例。您正试图从main中将指针值打印为十进制整数。main版本中的全局指针变量global_count尚未初始化,因此它将所有字节的起始值设置为0

您可以从共享库中删除globals.o,并且在main中只有一个global_count变量的实例。但是,为了让共享库看到main全局变量,必须使它们对它们可见。您可以通过在main的链接行中将-rdynamic添加到gcc的标志中来完成此操作。