1

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?

aneccodeal
  • 8,531
  • 7
  • 45
  • 74
  • Try declaring global_count with the 'volatile' keyword. – Peter L. Feb 21 '13 at 17:48
  • @Peter: OK, I tried putting 'volatile' in front of the declaration in the global.cpp file and recompiled everything. Still getting 0 in global_count when read from the main function so it seemed to have no effect. – aneccodeal Feb 21 '13 at 17:54

1 Answers1

2

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.

jxh
  • 69,070
  • 8
  • 110
  • 193
  • "You are trying to print out a pointer value as a decimal integer from main." ah, yes, true. I was trying to avoid a core dump there and wanted to see if the pointer was set. – aneccodeal Feb 21 '13 at 18:27