【问题标题】:How to use 2 C libs that export the same function names [duplicate]如何使用 2 个导出相同函数名称的 C 库 [重复]
【发布时间】:2009-03-25 11:35:45
【问题描述】:

重复以下问题:C function conflict


嗨, 在我当前的项目中,我必须使用某种接口库。函数名由这个接口给出,这个函数做什么由开发者选择。据我所知,项目应使用此功能,并且在编译时选择库及其功能。我尝试做的是通过包装另一个并在 mein 函数中调用它来同时使用现有的库和我的库:

其他库:

int function1 (int a) {
// do something
}

mylib:

int function1 (int a) {
//my code here
    otherlib::function1(a);
}

问题是我无权访问另一个库,而另一个库没有任何命名空间。我已经试过了

namespace old {
    #include "otherlib.h"
}

然后在我的函数中通过 old::function1 调用旧函数。只要它只是头文件,它就可以工作。该库将其符号导出回全局空间。还有类似

namespace new {
    function1 (int a) {
        ::function1(a);
    }
}

没用。最后但同样重要的是,我尝试了 ifdefs 并定义了建议的 here

但我没有成功。

任何想法如何解决这个问题?提前致谢。

编辑:我既无权访问旧库,也无权访问两个库都应在其中使用的项目。

EDIT2:至少旧库是静态库

【问题讨论】:

  • 我看到了这个,但我无权访问它们将用于的项目。

标签: c++ c word-wrap ambiguity


【解决方案1】:

C 中的命名空间使用库名称前缀解决,例如:

libfoo --> foo_function1
libbar --> bar_function1

这些前缀是实际的命名空间。所以如果你写 libbar

int bar_function1(int a) {
     function1(a);
}

这是解决问题的方法。

C 有命名空间 --- 它们只是称为前缀 ;)

另一种选择是通过动态加载库来执行各种肮脏的技巧,例如:

h1=dlopen("libfoo.so")
foo_function1=dlsym(h1,"function1")

h2=dlopen("libbar.so")
bar_function1=dlsym(h2,"function1")

【讨论】:

  • 感谢您的回答。不幸的是,我既无权访问旧库,也无权使用它的项目。至少旧库是静态的。
【解决方案2】:

似乎另一个库是 C,而您的代码是 C++。您可能会遇到重载问题(C++ 编译器会破坏符号——在符号名称中添加额外的内容以区分重载等)。

如果库是纯C的你可以试试:

extern "C" { // disable mangling of symbol names in the block
#include "otherlib.h"
}

namespace new_lib { // new is a reserved word
   int function1( int a ) {
      ::function1(a);
   }
}

我没试过。还可以考虑提供您收到的错误消息。

另一个选择是(如果库是动态的)动态加载库并调用函数。在linux下(我不知道windows)可以使用dlopen打开库,dlsym获取符号并调用:

// off the top of my head, not tried:
int function1( int a )
{
   int (*f)(int); // define the function pointer
   void * handle = dlopen( "library.so" );
   f = dlsym( handle, "function1" );
   f( a ); // calls function1(a) in the dynamic library
}

在这种情况下,由于您没有链接到库,因此不会出现符号冲突,但话又说回来,它仅对动态库有效,并且对于常规使用来说非常麻烦。

更新

如果您的用户不会直接使用“otherlib”(他们不会包含他们的标头)并且他们只会使用 C++,那么第一种方法可能是可能的(即使阅读起来很糟糕):

// newlib.h
namespace hideout {
   int f( int a );
}
using namespace hideout; // usually I would not put this on the header

// newlib.cpp
extern "C" { // if otherlib is C, else remove this line
#include "otherlib.h"
}
namespace hideout {
   int f( int a ) { return ::f( a*2 ); }
}

// main.cpp
#include "newlib.h"
int main()
{
   std::cout << f( 5 ) << std::endl;
}

它是如何工作的?用户代码只会看到 function1 的声明(在示例 f() 中),因为它们不包括 otherlib.h。在您的编译单元中,您会看到两个声明,但您可以通过命名空间的使用来区分。标题中的 using 语句不会打扰您,因为您完全符合您的 cpp。用户 main.cpp 将仅包含您的标头,因此编译器只会看到 hideout::f,并且由于 using 语句而在任何地方都可以看到它。链接器不会有问题,因为 C++ 符号被破坏以识别真正的命名空间:

// g++ 4.0 in macosx:
00002dbe T __ZN7hideout9function1Ei // namespace hideout, function1 takes int, returns int
00002db0 T _function1

如果用户代码将同时包含您的标头和 otherlib.h,那么它必须限定要调用的函数。

【讨论】:

  • 感谢您的回复。你的第一个建议对我不起作用。我无法控制函数名称,必须通过“使用命名空间 new_lib;”来更改范围,这会将 new_lib ns 放入已定义函数的全局中。我会尝试第二种方法。
【解决方案3】:

如果你真的很绝望,你可以编写一个使用命名空间或前缀或允许使用 dlsym 技巧的包装库。这个包装库需要动态链接(以避免符号冲突)。然后动态库可以安全地将旧的静态库嵌入其中。只要确保在制作动态包装库时不要从静态库中导出符号即可。

【讨论】:

    【解决方案4】:

    您无法在链接时解决此问题,因此您需要在运行时通过动态库解决此问题。一旦生成了库,这些函数的符号本质上就是烘焙它。如果两个库导出相同的符号,它们不能都静态链接。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-19
      • 2017-02-18
      • 2013-03-03
      • 1970-01-01
      • 2020-01-19
      • 2021-05-01
      • 1970-01-01
      相关资源
      最近更新 更多