我正在尝试修改iperf以支持其他协议(UDT)。编写UDT API使其镜像标准BSD调用:
socket(...);
bind(...);
listen(...);
我需要做的是,有条件地链接到UDT库,以便iperf中的这些调用将使用UDT代码而不是TCP堆栈的套接字接口。可以这样做吗?我总是可以加载库并使用UDT ::命名空间创建另一个条件路径,但是会有1)从TCP路径中复制很多,2)需要进行大量更改。如果我不清楚,请告诉我,有关如何实现这种动态链接的任何建议都表示赞赏。
编辑:
使用下面提到的dlopen()系列,我可以拥有以下程序流程:
解析cmd线参数 - >如果请求UDT,则加载库libudt - > 获取并存储所有UDT BSD函数的句柄(绑定,监听等)
此时我的函数指针存储了我的所有UDT函数。假设我将它们全部存储在一个名为udt_calls的结构中。现在,我对现有代码有问题,这些代码只会调用:
bind(...)
而不是:
udt_calls->bind(...)
有没有一种干净的方法我可以在我的udt_calls结构中使用我现在加载的函数指针全局覆盖整个程序中的任何BSD调用?
答案 0 :(得分:1)
是的,这可以做到。您需要使用动态库加载。在Windows中,这是使用LoadLibrary
完成的。在Linux或Unix中,它使用dlopen
和朋友完成。
您需要阅读文档并查看这些函数的示例。快速总结一下,您创建了一堆函数指针(通常在结构中完成,在Windows上有一些技巧可以将它们加载到C ++虚函数类中)。然后使用动态加载函数打开库,然后分配函数指针以指向库中的函数。
然后,使用函数指针(或C ++虚函数)进行函数调用。
修改:It looks like there are ways to use C++ virtual base classes in Unix as well.
编辑:我相信大多数系统都会使操作系统库使用“弱”符号。这意味着您可以定义自己的同名全局符号并覆盖OS库版本。尝试在您自己的程序中声明全局函数指针,以提供bind
和listen
的全局版本。
另一种选择可能是在结构中声明指针,然后使用预处理器定义,如:
#define bind udt_calls->bind