Вы можете определить символ, который должен быть слабым ссылкой к его определению. Тогда значение символа будет равно нулю, если определение отсутствует.
Например, предположим, что приведено ref.c, которое ссылается на функцию и переменную, которые могут быть или не быть; мы будем использовать его для создания libref.so (соответствует вашей библиотеке, в вашем вопросе):
#include <stdio.h>
void global_func(void);
void global_func(void) __attribute__ ((weak));
extern int global_variable __attribute__((weak));
void ref_func() {
printf("global_func = %p\n", global_func);
if (&global_variable)
global_variable++;
if (global_func)
global_func();
}
Здесь global_func
и global_variable
являются слабые ссылки на возможно-доступных функций и переменных. Этот код печатает адрес функции, приращает переменную, если она присутствует, и вызывает функцию, если она присутствует. (Обратите внимание, что адреса работы функции и переменной равны нулю, когда они не определены, поэтому &global_variable
, что вы должны сравнить с нулем.)
И пусть это def.c, который определяет global_func
и global_variable
; мы будем использовать его для создания libdef.so (соответствующий MPI, в вашем вопросе):
#include <stdio.h>
int global_variable;
void global_func(void) {
printf("Hi, from global_func! global_variable = %d\n", global_variable);
}
И, наконец, предположим, что у нас есть основной программы, main.c, который вызывает ref_func
из libref.so:
#include <stdio.h>
extern void ref_func(void);
int main(int argc, char **argv) {
printf("%s: ", argv[0]);
ref_func();
return 0;
}
Вот Makefile, который строит libref.so и libdef.so, а затем строит два исполняемых файла, оба из которых связывают с libref.so, но только один из которых будет связан с libdef.so:
all: ref-absent ref-present
ref-absent: main.o libref.so
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o [email protected]
ref-present: main.o libref.so libdef.so
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o [email protected]
lib%.so: %.o
$(CC) $(CFLAGS) $(LDFLAGS) -shared $^ -o [email protected]
ref.o def.o: CFLAGS += -fpic
clean:
rm -f *.o *.so ref-absent ref-present
Выполните сборку:
$ make
cc -c -o main.o main.c
cc -fpic -c -o ref.o ref.c
cc -shared ref.o -o libref.so
cc main.o libref.so -o ref-absent
cc -fpic -c -o def.o def.c
cc -shared def.o -o libdef.so
cc main.o libref.so libdef.so -o ref-present
$
Обратите внимание, что обе исх отсутствовавший и реф-настоящее связаны без проблем, даже если нет определения для global_name
в реф-отсутствующим.
Теперь мы можем запускать программы и видеть, что ref-missing пропускает вызов функции, а ref-present использует его.(Мы должны установить LD_LIBRARY_PATH, чтобы динамический компоновщик, чтобы найти наши общие библиотеки в текущем каталоге.)
$ LD_LIBRARY_PATH=. ./ref-absent
./ref-absent: global_func = (nil)
$ LD_LIBRARY_PATH=. ./ref-present
./ref-present: global_func = 0x15d4ac
Hi, from global_func! global_variable = 1
$
Хитрости для вас будет получать атрибут ((weak))
, прикрепленный к каждой декларации каждой MPI действуют ваши ссылки библиотеки , Однако, как показано в Ref.c, может быть несколько объявлений, и до тех пор, пока один из них упоминает слабый атрибут, все готово. Таким образом, вы, вероятно, сказать что-то вроде этого (я не знаю, MPI):
#include <mpi.h>
mpi_fake_type_t mpi_function_foo(mpi_arg_type_t) __attribute__((weak));
mpi_fake_type_t mpi_function_bar(mpi_other_arg_type_t) __attribute__((weak));
Каждая ссылка на функции MPI должен находиться в области видимости ((слабой)) декларации о том, что функция; вот как компилятор решает, какую ссылку на символ помещать в объектный файл. Вы хотите иметь автоматические тесты, чтобы убедиться, что вы случайно не создали никаких слабых ссылок.
У вас нет LD_BIND_NOW в вашей среде? – mvds