在共享库和主库之间共享全局数据 [英] Sharing global data between a shared library and main

查看:66
本文介绍了在共享库和主库之间共享全局数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为global_count的变量,我想在共享库和程序的主要部分(最终是其他库,但现在简化了测试用例)之间共享.

给出globals.cpp中的global_count声明:

 外部"C" {int * global_count;} 

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

  gcc -c global.cpp 

下面的

shared.cpp将用于创建 shared.so :

  #include< stdio.h>#include"global.h"extern"C" {void init_global_count(int * xp){printf(将全局计数初始化为:%d \ n",* xp);global_count = xp;};void print_global_count(){if(global_count){printf("global_count是:%d \ n",* global_count);} 别的 {printf("global_count *未初始化!\ n");}};} 

global.h:

 外部"C" {extern int * global_count;} 

main.cpp:

  #include< stdlib.h>#include< dlfcn.h>#include< stdio.h>#include"global.h"int答案= 42;int * gc_copy;typedef void(* func)();无效(* init_global_count)(int *);无效(* print_global_count)();空载(char * shared_lib){无效*句柄;handle = dlopen(shared_lib,RTLD_NOW | RTLD_GLOBAL);printf("load:dlopen \ n之后");if(!handle){printf(未加载!\ n");fflush(stdout);fputs(dlerror(),stderr);出口(1);} 别的 {printf("Loaded OK!\ n");fflush(stdout);void(* init_global_count)(int *)=(void(*)(int *))dlsym(句柄,"init_global_count");(* init_global_count)(& answer);void(* print_global_count)()=(void(*)())dlsym(句柄,"print_global_count");(* print_global_count)();}}int main(){printf("main ... \ n");load((char *)"../shared.so");如果(global_count)printf("main:global_count是:%d \ n",* global_count);返回0;} 

要编译共享的lib和main:

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

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

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

 主要...加载:dlopen之后装好了!初始化全局计数为:42global_count是:42 

因此,从* print_global_count()*(在shared.cpp中定义)内部报告的* global_count *是预期的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 的链接行中的 gcc 标记中添加 -rdynamic 来实现此目的.

I've got a variable called global_count that I would like to share between the shared library and the main part of the program (and ultimately other libs, but for now I've simplified the testcase).

Given the declaration of global_count in globals.cpp:

extern "C" {
  int* global_count;
}    

We compile to create a global.o file:

gcc -c global.cpp

shared.cpp below will be used to create shared.so:

#include <stdio.h>
#include "global.h"

extern "C" {


void init_global_count(int* xp) {
  printf("Initialize global count to: %d\n", *xp);
  global_count = xp;  
};

void print_global_count(){  
  if(global_count) {
    printf("global_count is: %d\n",*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 dlopen\n");
  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: %d\n", *global_count);
  return 0;
}

To compile the shared lib and 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

Note that we're linking in global.o in both of those compilations.

Now we run it and the output is:

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

So the *global_count* reported from inside *print_global_count()* (defined in shared.cpp) is 42 as expected. However, global_count is not reported from main because the global_count pointer has not been initialized - so the global_count in main.cpp is not the same as the global_count in shared.cpp.

I'm wondering if it's possible to do what I'm trying to do here (to share some global data between a .so and the module that loads the .so)? If so, do I need to link differently?

解决方案

All objects in a shared library need to be compiled as position independent (-fpic or -fPIC). So linking in globals.o into your shared library is in error.

You are actually creating two instances of the global_count pointer. You are trying to print out a pointer value as a decimal integer from main. The global pointer variable global_count in the main version is not yet initialized, so it has the starting value of all bytes set to 0.

You can remove globals.o from your shared library, and only have one instance of the global_count variable in main. However, for the shared library to see the main global variables, they have to be made visible to them. You can do this by adding -rdynamic to the flags to gcc in your link line for main.

这篇关于在共享库和主库之间共享全局数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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