首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用导出相同函数名的2C库

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

Stack Overflow用户
提问于 2009-03-25 11:35:45
回答 4查看 8.3K关注 0票数 5

重复下列问题:

嗨,在我当前的项目中,我必须使用某种接口库。函数名是由这个接口指定的,这个函数所做的是开发人员的选择。据我所知,一个项目将使用这个函数,当涉及到编译时,您可以选择lib,并选择它的功能。我试图做的是同时使用现有的lib和我的lib,方法是包装另一个库,并在mein函数中调用它:

其他库:

代码语言:javascript
运行
复制
int function1 (int a) {
// do something
}

米利卜:

代码语言:javascript
运行
复制
int function1 (int a) {
//my code here
    otherlib::function1(a);
}

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

代码语言:javascript
运行
复制
namespace old {
    #include "otherlib.h"
}

然后在我的函数中通过old::function 1调用旧函数。只要它只是头文件,它就能工作。lib将它的符号导出回全局空间。也是类似于

代码语言:javascript
运行
复制
namespace new {
    function1 (int a) {
        ::function1(a);
    }
}

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

但我没有成功。

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

编辑:我既不能访问旧库,也不能访问项目,这两个库都将在其中使用。

EDIT2:至少旧库是静态的

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-03-25 11:42:55

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

libfoo -> foo_function1

libbar -> bar_function1

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

代码语言:javascript
运行
复制
int bar_function1(int a) {
     function1(a);
}

这就是解决问题的方法。

C有名称空间--它们只是调用前缀;)

另一种选择是在动态加载库时执行各种肮脏的技巧,如:

代码语言:javascript
运行
复制
h1=dlopen("libfoo.so")
foo_function1=dlsym(h1,"function1")

h2=dlopen("libbar.so")
bar_function1=dlsym(h2,"function1")
票数 6
EN

Stack Overflow用户

发布于 2009-03-25 11:50:14

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

如果库是纯C,则可以尝试:

代码语言:javascript
运行
复制
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获取符号并调用它:

代码语言:javascript
运行
复制
// 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++,那么第一种方法是可能的(即使读起来很可怕):

代码语言:javascript
运行
复制
// 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()中),因为它们不包括therlib.h。在编译单元中,您可以看到这两个声明,但是通过使用命名空间来区分。标题中的using语句不会困扰您,因为您在cpp中完全符合条件。用户main.cpp将只包含您的头,所以编译器只会看到hideout::f,并且会因为using语句而在任何地方看到它。当C++符号标识真正的命名空间时,链接器将没有问题:

代码语言:javascript
运行
复制
// g++ 4.0 in macosx:
00002dbe T __ZN7hideout9function1Ei // namespace hideout, function1 takes int, returns int
00002db0 T _function1

如果用户代码同时包含头和其他函数,那么它必须限定要调用的函数。

票数 4
EN

Stack Overflow用户

发布于 2009-03-25 18:27:46

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/681200

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档