@ Предложение Ботье привело меня к написанию сценария компоновщика, как этот (пробелы в разделе PROVIDE значительны):
EXTERN(bar__4fooRi);
PROVIDE(_ZN4foo9barERi = bar__4fooRi);
Насколько я понял, это будет воспринимать bar__4fooRi
как внешнеопределенный символ (который это).Если поиск _ZN4foo9barERi
найден, но не определен, его место займет bar__4fooRi
.
Я так называю компоновщик из цепочки инструментов GNU (следите за порядком - сценарий должен быть после зависимогообъект, но до определяющей библиотеки):
g++ -o application application.o script.ld -lfoo
Похоже, это могло бы работать.
По крайней мере, в теории.
Компоновщик теперь относится к другим частям библиотеки, что, в свою очередь, зависит отдругие неразрешимые символы, включая (но не ограничиваясь ими) __throw
, __cp_pop_exception
и __builtin_delete
.Я понятия не имею, где эти функции определены в настоящее время.Joxean Koret показывает некоторые места в этом сообщении в блоге на основе догадок (__builtin_new
, вероятно, malloc
) - но я не настолько уверен.
Эти выводы приводят меня к выводу, чтобиблиотека опирается на другой стиль обработки исключений и, возможно, управления памятью.
РЕДАКТИРОВАТЬ: Результат может быть чисто академическим из-за изменений ABI, на что указывает @eukaryota, компоновщикСкрипт действительно может быть использован для «псевдонима» символов.Вот полный минимальный пример:
foo.h:
class Foo {
public:
int bar(int);
};
foo.cpp:
#include "foo.h"
int Foo::bar(int i) {
return i+21;
}
main.cpp:
class Foo {
public:
int baa(int); // use in-place "header" to simulate different name mangling algorithm
};
int main(int, char**) {
Foo f;
return f.baa(21);
}
script.ld:
EXTERN(_ZN3Foo3barEi);
PROVIDE(_ZN3Foo3baaEi = _ZN3Foo3barEi); /* declare "alias" */
Процесс сборки:
g++ -o libfoo.o -c foo.c
ar rvs libfoo.a libfoo.o # simulate building a library
g++ -o app main.o -L. script.ld -lfoo
app
скомпилирован, может быть выполнен и возвращает ожидаемый результат.