以下问题的重复: C功能冲突


嗨,在我当前的项目中,我必须使用某种接口lib。函数名称由此接口给出,此函数的作用是开发人员选择。据我所知,一个项目应使用此功能,并且在编译时,您选择了LIB及其功能。我尝试做的是同时使用现有的LIB和我的LIB,并将其称为Mein函数:

其他Lib:

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);
    }
}

不起作用。最后但并非最不重要的一点是我尝试了ifdefs并定义了建议 这里

但是我没有成功。

有什么想法解决这个问题吗?提前致谢。

编辑:我既不能使用旧的lib,也不可以使用两个液体的项目。

EDIT2:至少旧的lib是静态的。

有帮助吗?

解决方案

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

其他提示

似乎另一个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
}

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

更新

如果您的用户不会直接使用“其他Lib”(他们不包括标题),并且他们只能是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;
}

它是如何工作的?用户代码只会看到函数1的声明(示例f()中),因为它们不包括 其他Lib.H. 。在您的编译单元内,您会看到这两个声明,但您可以通过使用名称空间来区分。标题中的使用语句不会打扰您,因为您在CPP中完全有资格。用户 main.cpp 将仅包括您的标题,因此编译器只会看到 藏身处:: f, ,并且由于使用语句而将其视为任何地方。链接器将毫无问题,因为C ++符号被弄脏以识别真实名称空间:

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

如果用户代码同时包括您的标题和 其他Lib.H 然后,它必须限定要调用哪个功能。

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

您无法在链接时间解决此问题,因此您需要在运行时通过动态库解决它。这些功能的符号基本上是在库生成后烘烤的。如果两个库导出相同的符号,则它们都不能在静态上链接。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top