views:

736

answers:

5

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

+5  A: 

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")
Artyom
Thanks for your answer. Unfortunatly I neither have access to the old lib nor the project it shall be used in. And at least the old lib is static.
DaClown
+2  A: 

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.

David Rodríguez - dribeas
Thanks for your response. Your first suggestion doesn't work for me. I have no control over the function names would have to change the scope by 'using namespace new_lib;', and this put the new_lib ns into the global where the function in already defined. I'll try the second way.
DaClown
+1  A: 

Exactly this question was asked only yesterday, but SO's search facility has foxed all my attempts at finding it - when in gods name are they goinmg to replace this with a search that actually finds things?????

anon
Part of the burden is on us. We need to use (and avoid using) keywords that relate (don't relate) to our subject.
Les
"Exactly this question was asked only yesterday, but SO's search facility has foxed all my attempts at finding it" << this is soo true :) i dont like SO search facils either :)
Johannes Schaub - litb
+1  A: 

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.

Mr Fooz
+1  A: 

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.

MSN