Почему эта динамически загружаемая библиотека не может получить доступ к глобальным переменным программы загрузки? - PullRequest
0 голосов
/ 20 декабря 2010

Прежде всего, я видел это (<- ссылка), и оно не работает.Я использую OS X. </p>

ac:

#include <stdio.h>
#include <dlfcn.h>

int global_var = 0x9262;

int main(void) {
  void *handle = dlopen("libb.so", RTLD_LAZY);
  void (*func)(void);
  char *err;
  if (handle == NULL) {
    fprintf(stderr, "%s\n", dlerror());
    return 1;
  }
  func = dlsym(handle, "func");
  if ((err = dlerror()) != NULL) {
    fprintf(stderr, "%s\n", err);
    return 2;
  }
  global_var = 0x9263;
  func();
  return -dlclose(handle) * 3;
}

bc:

#include <stdio.h>

extern int global_var;

void func(void) {
  printf("0x%x\n", global_var);
}

Компиляция и запуск:

$ gcc -shared -rdynamic -fpic -o liba.so a.c
$ gcc -shared -fpic -o libb.so -L. -la b.c
$ gcc -fpic -o a a.c
$ ./a
0x9262

Почему нетэто печатает 0x9263?Я пробовал много комбинаций флагов компилятора, и ни одна из них не работает.

Ответы [ 2 ]

3 голосов
/ 20 декабря 2010

Вы создали два экземпляра global_var.Один определяется в liba.so, и это тот, на который ссылается b.c.

Другой определяется в a, и это тот, на который ссылается ваша main() функция.

Если вы хотите, чтобы ваша основная функция ссылалась на переменную в liba.so, ей нужно объявление extern вместо определения, и она должна ссылаться на саму эту библиотеку.

0 голосов
/ 20 декабря 2010

Интересный вопрос. Ответ тоже интересный.

Как упомянуто в его ответе caf, вы создали два определения global_var.

Чтобы сделать то, что вы пытаетесь достичь, вы должны убедиться, что global_var разрешен из основного исполняемого файла. для этого вам нужно будет создать файл импорта, в котором будет указано, что global_var импортируется из основного исполняемого файла. В файле импорта вы должны использовать # !. для этого.

Затем используйте этот файл импорта при создании библиотеки.

Также при компиляции основного двоичного файла убедитесь, что переменная global_var экспортирована. используйте соответствующие флаги компилятора.

На моем Unix Box я попробовал это, и оно работает.

# cat imp.imp
 #!.

 global_var

cc main.c -bexpall
cc  lib.c -bM:SRE -bnoentry -bI:./imp.imp -bexpall -o libb.so
...