4

以下问题的重复:C函数冲突


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

其他库:

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

我的库:

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 并在这里定义了建议

但我没有成功。

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

编辑:我既无权访问旧库,也无权访问两个库的项目。

EDIT2:至少旧库是静态库

4

4 回答 4

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")
于 2009-03-25T11:42:55.817 回答
4

好像另一个库是 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,那么它将必须限定要调用的函数。

于 2009-03-25T11:50:14.673 回答
1

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

于 2009-03-25T18:27:46.997 回答
1

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

于 2009-03-25T18:28:12.300 回答