【问题标题】:Decorate a function in a library装饰库中的函数
【发布时间】:2019-05-06 13:12:12
【问题描述】:

我有一个需要为其编写测试的共享库。假设库中有一个名为 func() 的函数:

// from the library
<some_type> func(<some_params>); // signature of the function func

Library 的文档指出,必须在特定条件下调用此函数。因此,为了测试该要求,我在测试文件中编写了自己的具有相同签名的函数 func():

// test.cpp
bool is_func_called = false;
<some_type> func(<some_params>) {
    is_func_called = true;
}

这种方法正确吗?我的 func() 实现是否保证覆盖库中的实现?

有时需要能够从库中装饰 func()(而不是覆盖它):

// test.cpp
bool is_func_called = false;
<some_type> func(<some_params>) {
    is_func_called = true;
    func(); // a call to the implementation in the library
}

如果我重写了库中的实现,如何访问它?

环境:Ubuntu,g++。

我目前正在使用共享库。但我实际上对(共享库和静态库)都感兴趣。

【问题讨论】:

  • 如果你定义了完全相同的签名,那么链接器会报错。
  • 不,它没有。它以某种方式选择了我的实现
  • 您不能对函数进行双重定义。如果出于测试目的,您只链接到您自己的实现,而不是库,这应该没问题。但我建议使用依赖注入和一些不错的测试库(例如 GoogleMock )而不是自己实现此功能。
  • 静态库还是动态库?对于动态库,您可以使用the LD_PRELOAD trick
  • @Someprogrammerdude 我目前正在使用共享库。但我实际上对两者都感兴趣。

标签: c++ linux overriding shared-libraries decorator


【解决方案1】:

嗯,你可以在 Linux 上使用 LD_LIBRARY_PRELOAD 技巧。

将您自己的func() 实现编译到共享库中。

gcc -shared -fPIC func.c -o func.so

然后在shell提示符下

> LD_LIBRARY_PRELOAD=func.so ./main

您的 func() 版本将被调用。

如果你想链接调用 - 首先用你的 func() 装饰原始 func(),那么代码应该是这样的

typedef a (*original_func_type)(B b);

a func(B b) {
    ... // whatever code you want
    original_func_type orig_func;
    orig_func = (original_func_type)dlsym(RTLD_NEXT, "func");
    return orig_func(b);
}

这是你想要的吗?

更新

更多文字tutorial。另一个tutorial。链接到tutorial on symbols/linking

【讨论】:

  • 感谢您的回答。我只想说我重写函数的方法实际上是有效的。我试过了。对吗?
  • @embedc 好吧,它应该可以工作,链接器应该首先选择你的实现。像我写的那样真正的装饰/链接对于测试、检查和注入目的更有趣。添加了另一个两部分教程的链接。
  • 您能否解释一下为什么链接器会首先选择我的实现?有什么规定吗?
  • @embedc 共享库中的典型符号是弱符号。 .o 文件之一中的典型代码会产生强符号。强符号将首先被链接器拾取。在 Linux 上添加了另一个教程链接 wrt 符号。
  • @embedc 您可以在nmobjdumpreadelf 的帮助下检查.o、.so 文件中的符号
猜你喜欢
  • 2018-11-12
  • 1970-01-01
  • 2018-10-25
  • 1970-01-01
  • 2014-07-21
  • 2019-05-26
  • 2018-02-07
  • 2010-11-26
相关资源
最近更新 更多