如何使用导出相同函数名的2个库

时间:2009-03-25 11:35:46

标签: c++ c wrapping ambiguity

重复以下问题:C function conflict


您好, 在我目前的项目中,我必须使用某种接口lib。函数名由这个接口给出,这个函数做的是开发人员的选择。据我所知,项目应该使用这个函数,当涉及到编译时,你可以选择lib并使用它来实现功能。我尝试做的是通过包装另一个并在mein函数中调用它来同时使用现有的lib和我的lib:

otherlib:

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

MYLIB:

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

问题是我无法访问其他lib,而其他lib没有任何名称空间。我已经尝试了

namespace old {
    #include "otherlib.h"
}

然后在我的函数中通过old :: function1调用旧函数。只要它是唯一的头文件,这就可以工作。 lib将它的符号输出回全球空间。还有像

这样的东西
namespace new {
    function1 (int a) {
        ::function1(a);
    }
}

没用。最后但并非最不重要的是,我尝试了ifdef并定义了建议的here

但我没有成功。

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

编辑:我既无法访问旧的lib也无法访问项目。两者都将使用。

EDIT2:至少旧的lib是静态的

4 个答案:

答案 0 :(得分:6)

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")

答案 1 :(得分:4)

好像其他lib是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);
   }
}

我没试过。另外,请考虑提供您收到的错误消息。

另一个选项是(如果库是动态的)动态加载lib并调用该函数。在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 ,则必须确定要调用的函数。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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