Выбор библиотеки для ссылки во время выполнения
Я пытаюсь изменить iperf для поддержки другого протокола (UDT). API UDT написан так, что он отражает стандартные вызовы BSD:
socket(...);
bind(...);
listen(...);
Тогда мне нужно условно связать библиотеку UDT, чтобы эти вызовы в iperf использовали код UDT вместо интерфейса сокета со стеком TCP. Можно ли это сделать? Я всегда мог просто загрузить библиотеку и иметь другой условный путь, используя пространство имен UDT::, но было бы 1) много дублирования из пути TCP и 2) было бы много изменений там, где, возможно, не должно быть ни одного. Пожалуйста, дайте мне знать, если мне неясно, приветствуются любые предложения о том, как добиться этого динамического связывания.
Редактировать:
Используя семейство dlopen(), упомянутое ниже, у меня может быть следующий поток программ:
Разобрать параметры строки cmd -> если запрашивается UDT, загрузить библиотеку libudt -> get и сохранить дескрипторы для всех функций BSD UDT (bind, listen и т. Д.)
На данный момент у меня есть указатели функций, хранящиеся со всеми моими функциями UDT. Допустим, я храню их все в структуре с именем udt_calls. Теперь у меня есть проблема с существующим кодом, который просто делает такие вызовы:
bind(...)
скорее, чем:
udt_calls->bind(...)
Есть ли чистый способ, которым я могу глобально переопределить любой вызов BSD по всей программе с помощью моих теперь загруженных указателей на функции в моей структуре udt_calls?
1 ответ
Да, это можно сделать. Вам нужно использовать динамическую загрузку библиотеки. В Windows это делается с помощью LoadLibrary
, В Linux или Unix это делается с помощью dlopen
и друзья.
Вы захотите прочитать документацию и посмотреть примеры для этих функций. Вкратце, вы создаете несколько указателей на функции (часто это делается в структуре, а в Windows есть несколько хитростей, позволяющих загрузить их в класс виртуальных функций C++). Затем вы используете функции динамической загрузки, чтобы открыть библиотеку, а затем назначаете указатели на функции, чтобы они указывали на функции внутри библиотеки.
Затем вы выполняете вызовы функций, используя указатели функций (или виртуальные функции C++).
Редактировать: Похоже, есть способы использовать виртуальные базовые классы C++ в Unix.
Изменить: я считаю, что большинство систем заставляют библиотеки операционной системы использовать "слабые" символы. Это означает, что вы можете определить свои собственные глобальные символы с тем же именем и переопределить версию библиотеки ОС. Попробуйте объявить глобальные указатели функций в вашей собственной программе, чтобы обеспечить глобальные версии bind
а также listen
,
Другим вариантом может быть объявление ваших указателей в структуре, а затем использование препроцессора, например:
#define bind udt_calls->bind