1

共有ライブラリとプログラムの主要部分(そして最終的には他のライブラリ)の間で共有したいglobal_countという変数がありますが、今のところテストケースを簡略化しています。

globals.cppでのglobal_countの宣言を考えると:

extern "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("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;
}

共有ライブラリとメインをコンパイルするには:

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()*(shared.cppで定義)の内部から報告される* global_count *は、予想どおり42です。ただし、global_countポインターが初期化されていないため、global_countはmainから報告されません。したがって、main.cppのglobal_countは、shared.cppのglobal_countと同じではありません。

ここでやろうとしていることを実行できるかどうか疑問に思っています(.soと.soをロードするモジュールの間でグローバルデータを共有するため)?もしそうなら、私は別の方法でリンクする必要がありますか?

4

1 に答える 1

2

-fpic共有ライブラリ内のすべてのオブジェクトは、位置に依存しない (または)としてコンパイルする必要があります-fPIC。したがってglobals.o、共有ライブラリへのリンクはエラーです。

実際には、global_countポインターの 2 つのインスタンスを作成しています。から 10 進整数としてポインター値を出力しようとしていますmain。バージョンのグローバル ポインタ変数global_countmainまだ初期化されていないため、すべてのバイトの開始値が に設定されてい0ます。

globals.o共有ライブラリから削除して、global_count変数のインスタンスを main に 1 つだけ持つことができます。ただし、共有ライブラリがmainグローバル変数を参照できるようにするには、共有ライブラリが参照できるようにする必要があります。のリンク行に-rdynamicフラグを追加することで、これを行うことができます。gccmain

于 2013-02-21T18:11:05.853 に答える