I am using a C library (libgretl) from C++ and some of its functions conflict with my code, so I wanted to wrap it in a namespace, like this:
namespace libgretl {
extern "C" {
#include <gretl/libgretl.h>
}}
However, this does not compile, I get "undefined" errors from gcc files (using mingw32 with gcc 4.5.2 on Windows).
The first errors come from the following code block of file c++/cstddef:
_GLIBCXX_BEGIN_NAMESPACE(std)
using ::ptrdiff_t;
using ::size_t;
_GLIBCXX_END_NAMESPACE
where the macros expand respectively to namespace std { and }. There are more errors after these.
Omitting the extern "C" directive does not help. Using an anonymous namespace reduces the amount of errors, but it still won't compile.
My question is therefore if there is some way to include such a C library and place its functions into a namespace, without changing the gcc or the library's source files?
Thanks.
Michal
You can't do it. Namespaces are not just source code decorations, they are mangled to object symbols by compiler.
Native C function foo() in library will be available by symbol _foo in object file, but calling bar::foo() will generate reference to, for example, #N3barfoo. As result, linker error will occur.
You may create "proxy" functions in separate source file, including original library header only in this source and putting all proxy functions to namespace.
You don't get to simply wrap a namespace around an external declaration and have it appear within that namespace... the item (function, global) must have been built within that namespace from the start. Since C doesn't support namespace resolution, this could not have been the case.
You need to change your own code to accommodate this library, unless you're willing to chante the library itself.
In order to refer to a non-namespace'd item that conflicts with your own namespace'd item, refer to ::item().
I guess the C library was compiled as C, which means namespaces are not included and not supported in the compiled code. Thus, your compiled C library cannot be in a namespace. Altering the header by encapsulating the include will not change that.
You can still encapsulate your own code in a namespace.
Related
I have a source code of some library. There is a function that is only declared (in a header file), but not defined in the source code.
extern "C" {
extern int theFunc(int);
}
What is the reason to have only a declaration of a function in a library?
In addition of Mike Kinghan's answer (which covers most of the cases), there is also a (rather unusual) reason to declare in the library header file a function not implemented in that library. Sometimes, that library expects a plugin and the user is expected to provide such a plugin (in some way, perhaps passing the plugin file name to some other function). The library would use dynamic loading techniques (such as dlopen(3) on Linux) to install such a plugin. And it would fetch some particular function (with dlsym(3) on Linux) from the plugin. Then it makes sense to declare, but not define such a plugin function, in the library headers.
I do admit that this case is unusual and contrived.
For a concrete example, read about GCC plugins. Your plugin should #include "gcc-plugin.h" which indirectly declares
/* Declaration for "plugin_init" function so that it doesn't need to be
duplicated in every plugin. */
extern int plugin_init (struct plugin_name_args *plugin_info,
struct plugin_gcc_version *version);
but that plugin_init should be defined by your plugin code. Then GCC would dlopen your plugin, using something equivalent to
void*plhdl = dlopen("/home/you/yourplugin.so", RTLD_NOW);
and later get a function pointer using
typeof(plugin_init)* funptr = dlsym(plhdl, "plugin_init");
Notice that the symbol plugin_init does not appear in the code segment of GCC.
Another example is the Qt framework (a set of libraries). Read about Qt plugins.
I am trying to link to an external library, on which I have no control, that doesn't have any namespace for its functions.
Since I don't want to have conflicts with the names defined in that library: how to include the external headers in a namespace that I would create myself?
I know that the following code doesn't work, but the spirit of the question is there:
namespace extLib {
#include "externalFolder/externalHeader.h"
}
If you are working with a header-only library, your mentioned approach will probably work. At least I can't think of any issue right away.
But if you have a compiled library that you have to link to, there is no way to put the library functions themselves into their own namespace (at least not without recompiling your own version of said library). That's because in the .dll or .so or what have you, each function has a mangled name that includes all namespaces (example). When you eventually link against the library, you can only "reach" those functions under that exact mangled name, which requires that your function calls are against that same (or, in your case, no) namespace as the compiled versions.
The "classic" workaround is to write a thin wrapper around the library, where for every exposed function, you do:
wrapper.h:
namespace libraryWrapper
{
void bar(int);
}
wrapper.cpp
#include "realLibrary.h" // Defines bar(int)
void libraryWrapper::bar(int x)
{
::bar(x)
}
Basic example
I have several C++ classes which I decided to compile into separate library usable by other applications. Therefore I made a simple C-compatible envelope which wraps C++ classes. The function definitions in the header file are put in extern "C" block.
When I compile this using MinGW g++, I get shared library with decorated function names. Each function name has suffix #ars_size. To get rid of this names I passed -Wl,--kill-at argument to g++. Then I finally got undecorated names.
Then I made a simple C++/Qt application which serves as a tester of the new library. Unfortunately when I include the library's header file into my C++ application, I get linking errors:
release/mainwindow.o:mainwindow.cpp:(.text+0xd6f): undefined reference to `_imp__TdbGetLastErr#12'
release/mainwindow.o:mainwindow.cpp:(.text+0x1163): undefined reference to `_imp__TdbGetAsyncErr#12'
release/mainwindow.o:mainwindow.cpp:(.text+0x166f): undefined reference to `_imp__TdbStop#4'
release/mainwindow.o:mainwindow.cpp:(.text+0x1698): undefined reference to `_imp__TdbForceTrigger#0'
...
To get rid of these errors I have to exclude -Wl,--kill-at during compiling of the library. But then the library is not compatible with C applications. I believe the key is to make MinGW g++ to link undecorated functions. Please does anybody know, how to do this?
EDIT: Adding more details requested in comments.
When compiling the library, I include its header (with extern "C") from the
source code, so the compiler should be aware of extern "C".
The library is not so simple wrapper. Actually it creates several C++ objects
which are operated using handles from C applications. Also it catches
exceptions from C++ classes etc.
Klasyc
I'm trying to use two large, complex linear algebra libraries which define many of the same functions. I can't rewrite (legally in one case, but technically in both) either of them. Let's call them "special" and "normal" because I only call a couple functions from special. To consistently call functions defined in normal.h and only in some cases from special.h, I've done something like this:
namespace special_space
{
#include "special.h" // Defines foo()
}
#include "normal.h" // Defines foo()
int main() {
foo(); // Calls foo() defined in normal.h
special_space::foo(); // Calls foo() defined in special.h
}
With g++-4.4, which was the default where I was developing this, the code compiles and links without warnings, and it executes as I would expect and as I want. This seems to be consistent across platforms, various Linux, Unix and BSD environments. But! if I compile with g++ >4.4, I get warnings about multiple foo() definitions:
In file special.h::line:col: warning: declaration of ‘void
special_space::foo()’ with C language linkage [enabled by default]
The resulting executable then segfaults at the call to special_space::foo(). I /think/ that specifying extern "C++" in the definitions found in special.h might fix this, but I'm not allowed to change special.h. So what should I do? More specifically:
1) Is it safe to use g++-4.4? If so -- what changed in subsequent versions and why?
2) If specifying the C++ linkage model really would fix this, is there a way to tell ld to use it by default?
3) If neither of those -- is there another way to call functions from libraries that define functions of the same name?
So as I posted in a comment, wrap the headers includes with
#ifdef __cplusplus
extern "C" {
#endif
#include normal.h
#ifdef __cplusplus
}
#endif
Do this with both headers.
Basically, since you're linking c libraries from c++, which does name mangling (this is what allowes overloading), your calls to the symbols in your c lib were being mangled by the linker. The #ifdef __cplusplus tells the linker not to mangle the names for those specific function symbols.
Ideally, the creators of the library should include this in their headers but you mentioned that you have no control over that. I had a similar problem with some generated code. I had to wrap all my header includes of the generated code in this to allow C++ to call it.
What I don't know, is how it ever worked without this. I've definitely had to do this going back to gcc < 4.4.
Lets say I have a C++ program and I want to call functions from a C object file in it. The constraint is that I'm not allowed to make any changes to the C source files.
In this case I would include the C header as extern "C" in my C++ file, call the function, compile the C object using gcc -c, and pass the result to g++ along with the actual C++ sources.
I guess what I would also do is to put the C-header #include inside a named namespace block in the C++ file, as to keep the local namespace clean (who knows what other fancy stuff there is in the .h file).
What now if I need to call functions from two C object files. Lets say that they have different signatures. But there are also some duplicate functions in the object files. Wouldn't my linker blow up at this point if I tried to pass both objects to g++ at the same time? Same for globals.
Again: I'm not allowed to change ANY of the C sources. Else I would just rename the .c files to .cxx, wrap their contents and the contents of the corresponding headers inside namespace bla { } and feed everything to g++.
(Yes, C is not a subset of C++, as has already been mentioned in one of the comments)
Your last paragraph has a good solution - why not make a C++ file something like this:
namespace c_namespace_1 {
#include "CFile1.c"
}
namespace c_namespace_2 {
#include "CFile2.c"
}
And so on.... then you could compile this file as C++ and not have to modify the original sources.
You could bring the C executable codes in as individual binary data files and handle the function pointer casting yourself - basically do the linker's job for it. If the binary directly wouldn't work, get the assembler output of the C files and wrap them in functions similiar to the above suggestion of namespaces.
How about compile each C subsystem to its own LIB file, then compile a separate C++ LIB file that includes the appropriate C LIB and provides wrapped function calls to only the C functions in its .LIB
ie:
file1.c => file1.lib
file2.c => file2.lib
Wrapper1.cpp + file1.lib => Wrapper1.lib
Wrapper2.cpp + file2.lib => Wrapper2.lib
Application.cpp + Wrapper1.lib + wrapper2.lib => Application.exe
Note that this off the top of my head and I have no idea if the linker will still go boom
Of course you could compile Wrapper1 and Wrapper2 to dll's instead of Lib's and that would ensure the linker doesn't go boom!
This is pretty hacky, but one solution is to rename the function(s) in question via macros, so that they have different names as far as the linker is concerned.
For example, if you have too functions called foo, one of which takes an int and the other of which takes a double, in files IntFoo.c and DoubleFoo.c, you can compile them like this:
cc -Dfoo=IntFoo -o IntFoo.o IntFoo.c
cc -Dfoo=DoubleFoo -o DoubleFoo.o DoubleFoo.c
Then in your C++, you can do this:
#define foo IntFoo
extern "C" {
#include "IntFoo.h"
}
#define foo DoubleFoo
extern "C" {
#include "DoubleFoo.h"
}
#undef foo
There are lot of caveats here: you have to ensure that the symbol foo is used only as the name of the function you want, you have to ensure that you define the macros appropriately everywhere that the symbol foo is used. If there are duplicate symbols, you have to define macros for those as well.
It is probably a much better solution to just fix the C files.