Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use 2 C libs that export the same function names [duplicate]

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

like image 593
DaClown Avatar asked Dec 17 '22 08:12

DaClown


2 Answers

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")
like image 133
Artyom Avatar answered Dec 19 '22 21:12

Artyom


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.

like image 42
David Rodríguez - dribeas Avatar answered Dec 19 '22 20:12

David Rodríguez - dribeas