选择在运行时链接的库
我正在尝试修改 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 调用?
I am trying to modify iperf to support another protocol (UDT). The UDT API is written such that it mirrors the standard BSD calls:
socket(...);
bind(...);
listen(...);
What I need to do then, is conditionally link with the UDT library so that these calls in iperf will use the UDT code instead of the socket interface to the TCP stack. Can this be done? I could always just load the library and have another conditional path using the UDT:: namespace but there would 1) be a lot of duplication from the TCP path and 2) be a lot of changes where maybe there need be none. Please let me know if I'm not being clear, any suggestions of how to achieve this dynamic linking is appreciated.
Edit:
Using the dlopen() family mentioned below, I could have the following program flow:
Parse cmd line params -> if UDT is requested, load library libudt ->
get and store handles to all the UDT BSD functions (bind, listen, etc)
At this point I have function pointers stored with all my UDT functions. Let's say I'm storing them all in a struct called udt_calls. Now, I have a problem with the existing code which just makes calls like:
bind(...)
rather than:
udt_calls->bind(...)
Is there a clean way I can globally override any BSD call throughout the program with my now loaded function pointers in my udt_calls struct?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的,这是可以做到的。您需要使用动态库加载。在 Windows 中,这是使用 LoadLibrary 完成的。在 Linux 或 Unix 中,这是使用 dlopen 和朋友完成的。
您需要阅读文档并查看这些函数的示例。一个简单的总结是,您创建了一堆函数指针(通常在结构体中完成,并且在 Windows 上有一些技巧可以使它们加载到 C++ 虚拟函数类中)。然后,您使用动态加载函数打开库,然后分配函数指针以指向库内的函数。
然后,您可以使用函数指针(或 C++ 虚拟函数)进行函数调用。
编辑: 看起来也有办法在 Unix 中使用 C++ 虚拟基类。
编辑:我相信大多数系统使操作系统库使用“弱”符号。这意味着您可以定义自己的同名全局符号并覆盖操作系统库版本。尝试在您自己的程序中声明全局函数指针,以提供
bind
和listen
的全局版本。另一种选择可能是在结构中声明指针,然后使用预处理器定义,例如:
Yes this can be done. You need to use dynamic library loading. In Windows this is done using
LoadLibrary
. In Linux or Unix it is done usingdlopen
and friends.You'll want to read the documentation and look at samples for those functions. A quick summary is that you create a bunch of function pointers (often done in a struct, and on Windows there are some tricks to make them load into a C++ virtual function class). Then you use the dynamic load functions to open a library and then assign your function pointers to point to the functions inside the library.
Then, you make your function calls using the function pointers (or C++ virtual functions).
Edit: It looks like there are ways to use C++ virtual base classes in Unix as well.
Edit: I believe that most systems make the operating system libraries use "weak" symbols. That means that you can define your own global symbols of the same name and override the OS library version. Try declaring global function pointers in your own program to provide global versions of
bind
andlisten
.Another option may be to declare your pointers in a struct and then use preprocessor defines like: