Поскольку вы не можете перестроить ни одну из библиотек и поскольку библиотекам не разрешено находиться в одном и том же «пространстве имен динамического компоновщика» из-за конфликтующих символов, ваш единственный выбор - изолировать их .
Этого можно добиться, используя dlopen("lib*.so", RTLD_LOCAL)
(для одной или обеих библиотек) вместо прямой ссылки на них.
Это может быть осуществимо, если вам нужно всего лишь несколько символов, например, libfoo.so
- вы можете просто использовать dlsym
вместо прямого вызова функций.
Если у вас «слишком много» зависимостей в обеих библиотеках, ваше другое решение может заключаться в создании библиотеки «interposer». Допустим, вы хотите вставить libbar.so
, и вам нужно bar1()
, bar2()
, ... bar1000()
из него.
Напишите (или сгенерируйте с помощью простого сценария Perl) исходный файл, который выглядит следующим образом:
static void *handle;
void *bar1()
{
static void* (*pfn)(void *arg1, void *arg2, void *arg3, ..., argN);
if (pfn == NULL) {
if (handle == NULL)
handle = dlopen("libbar.so", RTLD_LOCAL|RTLD_LAZY);
pfn = dlsym(handle, "bar1");
}
return (*pfn)(arg1, arg2, ..., argN);
}
... repeat for all other libbar functions you depend on
Теперь скомпилируйте и свяжите этот источник в libbar_interposer.so
и свяжите ваше приложение с ним (это не будет работать для C++
из-за искажения имени, только для обычного - C
). Вуаля, источник изменений в приложении отсутствует, и вы по-прежнему изолировали libbar.so
, поэтому его символы не будут видны остальной части приложения и, в частности, не будут конфликтовать с какими-либо символами в libpng
.