重复以下问题: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是静态的
答案 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)
您无法在链接时解决此问题,因此您需要在运行时通过动态库解决此问题。一旦生成库,这些函数的符号基本上就被烘焙了。如果两个库导出相同的符号,则它们不能同时静态链接。