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

发布于 2024-07-15 22:48:55 字数 1034 浏览 14 评论 0原文

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


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

otherlib:

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

mylib:

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

但我没有成功。

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

编辑:我既无法访问旧库,也无法访问两个库都应使用的项目。

编辑2:至少旧库是静态库

Duplicate of the following question: C function conflict


Hi,
in my current project I have to use some kind of interface lib. The function names are given by this interface, what this functions do is developers choice. As far as I can tell a project shall use this functions and when it comes to compiling you choose the lib and with it the functionality. What I try to do is to use an existing lib and my lib at the same time by wrapping the other and call it in mein functions:

otherlib:

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

mylib:

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

Problem is I don't have access to the other lib and the other lib doesn't have any namespaces. I already tried

namespace old {
    #include "otherlib.h"
}

and then call the old function by old::function1 in my function. This works as long as it's only header file. The lib exports it's symbol back into global space. Also something like

namespace new {
    function1 (int a) {
        ::function1(a);
    }
}

didn't work. Last but not least I tried ifdefs and defines suggested here

but I wasn't successful.

Any ideas how to solve this? Thanks in advance.

EDIT: I neither have access to the old lib nor the project both libs shall be used in.

EDIT2: at least the old lib is a static one

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

酒废 2024-07-22 22:48:55

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

Namespaces in C solved using library names prefixes like:

libfoo --> foo_function1
libbar --> bar_function1

These prefixes are actual namespaces. so if you write libbar

int bar_function1(int a) {
     function1(a);
}

This is the way to solve problems.

C has namespaces --- they just called prefixes ;)

Another option is to do various dirty tricks with dynamic loading of libraries like:

h1=dlopen("libfoo.so")
foo_function1=dlsym(h1,"function1")

h2=dlopen("libbar.so")
bar_function1=dlsym(h2,"function1")
凤舞天涯 2024-07-22 22:48:55

看起来好像另一个库是 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,并且由于使用语句而在任何地方都可以看到它。 链接器不会有任何问题,因为 C++ 符号被破坏以识别真正的命名空间:

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

如果用户代码将包含您的头文件和 otherlib.h ,那么它将必须限定它想要调用的函数。

It seems as if the other lib is C and your code is C++. You can be running into a mangling problem (C++ compilers mangle the symbols -- add extra stuff in the symbol name do differentiate overloads and the like).

If the library is pure C you can try:

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

I have not tried it. Also consider providing the error messages you are getting.

Another option would be (if the library is dynamic) dynamically loading the lib and calling the function. In linux (I don't know about windows) you can use dlopen to open the library, dlsym to obtain the symbol and call it:

// 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
}

In this case, as you are not linking against the library you won't get a symbol conflict, but then again, it is only valid for dynamic libraries and it is quite cumbersome for regular usage.

UPDATE

If your users will not use 'otherlib' directly (they won't include their headers) and they will be only C++, then the first approach could be possible (even if horrible to read):

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

How does it work? User code will only see a declaration of function1 (in the example f()) as they are not including otherlib.h. Inside your compilation unit you see the two declarations but you differentiate through the use of the namespace. The using statement in the header does not bother you as you are fully qualifying in your cpp. The user main.cpp will include only your header, so the compiler will only see hideout::f, and will see it anywhere due to the using statement. The linker will have no problem as the C++ symbol is mangled identifying the real namespace:

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

If user code will include both your header and otherlib.h then it will have to qualify which function it wants to call.

剩一世无双 2024-07-22 22:48:55

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

If you're really desperate, you could write a wrapper library that uses namespaces or prefixes or allows for the dlsym trick. This wrapper library would need to be dynamically linked (to avoid symbol conflicts). The dynamic library could then safely have the old static library embedded in it. Just make sure you don't export the symbols from the static library when making the dynamic wrapper library.

失眠症患者 2024-07-22 22:48:55

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

You can't resolve this at link time, so you'll need to resolve it at runtime via dynamic libraries. The symbol for those functions is essentially baked it once the library has been generated. If two libraries export the same symbol, they cannot both be linked with statically.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文