I am having trouble with a piece of C code that is compiled as C++ producing a linker error from a 3rd package.
The setup is I have lua, oolua, and my program which utilizes the two. This project was moved from luabind due to its horrid build process. My code occasionally will throw an exception (which is expected) when constructing an object, and oolua does not handle this error.
From the reading I've done compiling lua as C++ should alleviate this problem and cause the program to not just quit, but the problem is oolua doesn't like lua being C++ for some reason and I cannot find references to why this could be.
tl;dr: If C code is compiled as C++ what problems could occur with linking assuming it compiles correctly?
When Lua is compiled as C++ it actually uses C++ name mangling and the normal headers should be used by C++. Don't be confused by the lua.hpp header. That should only be used for C++ when Lua is compiled as C. As a result when you compile Lua as C++ you should not use extern "C". Unfortunately OOLua does use extern "C" here. You could try modifying the header in OOLua to not use extern "C" and then recompile OOLua or file a bug with them to fix it properly.
Unfortunately not many people seem to be aware of the pitfalls of using Lua with C++ so many projects assume Lua is compiled as C as normal.
Long explanation:
When Lua is compiled as C there are no extern statements and therefore all functions get the default (extern "C"). When C files use Lua they use the normal header files which again contain no extern statements so the compiler presumes everything to be extern "C" and it all matches the library. If you use Lua from C++ you use lua.hpp which contains the extern "C" block so your compiler knows that Lua is extern "C".
When Lua is compiled as C++ there are no extern statements so the compiler assumes all functions in Lua are extern "C++". You can no longer use Lua directly from C. If you use Lua from C++ with the lua.hpp then it sees the extern "C" block, assumes Lua functions are extern "C" and fails at link time because of the wrong mangling. If you use the normal headers directly from C++ then there are no extern statements so extern "C++" is assumed. This matches the library and all is OK.
What OOLua does is it includes the normal headers but has it's own extern "C" around it so the compiler uses extern "C" linkage for all Lua functions when they are in fact using C++ linkage, the mangling is wrong and you get lots of linker errors about missing symbols.
Related
I saw in a C++ program that dlfcn library is used for dynamically
linking to a shared object library chosen by the user of the C++
program during runtime, and for calling functions in the chosen
shared object library via dlsym() and other functions in dlfcn.
Assume the user chooses a shared object library called x.so during runtime. x.so was compiled from a cpp file with definitions
of functions enclosed within extern "C". A comment in the cpp file
says that the usage of extern "C" is important but without further
explanation, and I wonder why?
Is it correct that there is only C++ code and no C code involved here? So is extern "C" not necessarily only used when mixing C and C++
code together?
Does whether dlfcn library is statically or dynamically linked to the C++ program matters to the questions above?
Now compare to a simpler case, where the shared object library is
known much earlier than runtime, and the author of the C++ program
specifies it in the C++ program without using dlfcn before compiling it, and then
dynamically links the shared object library and the C++ program
during runtime. In this case, is `extern "C" still necessary in the
cpp file which was compiled into the shared object library?
Thanks.
extern "C" changes the linkage, and affects name mangling. See What is name mangling, and how does it work?
Without it, exported names in the compiled object will normally be mangled. That means that they cannot be used from C. It also means that looking them up via dlsym() requires using the mangled name.
Is it correct that there is only C++ code and no C code involved here? So is extern "C" not necessarily used when mixing C and C++ code together?
It is not clear what you mean here. If you are compiling C++, then only C++ code is involved at this stage. If you are then linking in any way with a module written in C, then C is involved. If you need an external C library or program to link to your C++-defined functions, then they need to be declared extern "C".
Does whether dlfcn library is statically or dynamically linked to the C++ program matters to the questions above?
No (perhaps you should have explained why you think it might matter).
Now compare to a simpler case, where the shared object library is known much earlier than runtime, and the author of the C++ program specifies it in the C++ program without using dlfcn before compiling it, and then dynamically links the shared object library and the C++ program during runtime. In this case, is `extern "C" still necessary in the cpp file which was compiled into the shared object library?
It is necessary that the declared linkage of the symbols is consistent in the two C++ modules. Certainly, you could remove extern "C" if the modules are both C++. But if one module declares the symbol as extern "C" then the other must also.
I know OpenCL has a C++ binder, but I use a third party library which is currently only working with CL.h. I want to write my program in C++. Is it safe to include cl.h in a C++ program and work with that in C style?
I saw some examples of including cl.h in C++ and they seem to be working. However, I don't know for sure. Is there any specific situation that may cause problems?
Yes. It is a C/C++ header with proper "extern "C" " guards.
http://www.khronos.org/registry/cl/api/1.0/cl.h
If it's a C header, you can wrap it in extern "C" directives:
extern "C"
{
#include "CL.h"
}
this tells the linker not to apply name mangling when looking for the functions declared in the header.
I'm attempting to use SQLite in a c++ program. My knowledge of C/C++ is limited as I've mostly used Java to this point. I had some classes in college but its been a while and we never covered anything like this. SQLite is written in C. When compiling the program how would you do this? (I have MinGW installed on my windows platform so gcc and g++ are what i use to compile.)
You protect the C headers in your C++ code by
extern "C" {
// your includes here
}
and that should be all---g++ should happily link code from both gcc and g++. The extern "C" ... trick is also used in C++ system headers and many libraries, just look at the headers that came with your g++ installation or some suitable Open Source projects. Here is a Boost example:
edd#max:~$ grep 'extern "C"' /usr/include/boost/date_time/*
/usr/include/boost/date_time/filetime_functions.hpp: extern "C" {
/usr/include/boost/date_time/filetime_functions.hpp: } // extern "C"
edd#max:~$
Edit: Thanks to delnan for an attentive comment---this is from the sqlite3.h header itself:
/*
** Make sure we can call this stuff from C++.
*/
#ifdef __cplusplus
extern "C" {
#endif
so this is of course already taken care of.
C++ achieves compatibility with C through the use of extern "C" declarations. There are some good explanations of what extern "C" means and why it is needed at this SO question: Why do we need extern āCā{ #include } in C++?. Virtually all C-based libraries, including sqlite, provide for automatic C++ compatibility by including extern "C" in their header files.
Therefore, SQLite will work without any special handling on your part (other than including the header and the library as you normally would for a C or a C++ library)...
/* my_sqlite_program.cpp */
#include <sqlite3.h>
int main()
{
...call sqlite functions...
}
compile with
g++ -Wall -Werror my_sqlite_program.cpp -lsqlite3 -o my_sqlite_program
For SQLite in specific, there's nothing really complicated about it.
If you're using a dynamic or static library, you just include their headers and link against the proper lib files.
If you're including SQLite fully inside your app, you'll need to include all the source files in your project and build them as well, and include the headers as needed (using it as a static/dynamic library might be nicer though).
If you need to use C code in files compiled as C++, Dirk's answer is correct, but that's not needed for SQLite.
How can you call C programs from C++ source code?
By using a facility called as linkage specification provided by the compilers. The specification tells the compiler how to link the source code.
Linkage specification is of the format
extern "Language_Type"
{
}
In your case you can wrap your SQLlite C functions like
extern "C"
{
//SQLite function declarations
}
This should enable you to get it working but Since you are trying to call SQlite c functions from C++, SQLite already provides some wrappers for achieving what you are trying to achieve. Check more details on SQLite website. Also, some open source projects also provide what you want. Check CppSQLite
Hope this helps!
I have a small program that I can compile with GCC and ICC without any difficulties, but I would also like the code to work with G++ and ICPC. I tried to add this:
#ifdef __cplusplus
extern "C" {
#endif
at the beginning and this:
#ifdef __cplusplus
}
#endif
at the end of all the header files, but I still get several `undefined reference to "..."' errors.
I think you're getting it wrong... The extern C is for disabling the function mangling; so if you do it just for the header files, when you try to link your mangled object code, the declared function names won't match with the function names in the object file.
Anyway, the extern C won't add any portability if the whole application is being compiled and linked with the same C++ compiler, it's intended for mixing C libraries with C++ code.
If your code is in the common subset of C and C++, you should be already able to compile it with either compiler, but I cannot see the reason to do that (besides working on the principle of least surprise, as C++ is more strict with some things).
You get undefined references because the declaration and the definition are not matching if you put extern "C", which prevents name mangling from happening: but in this case this is happening only in your header files.
If one of the undefined references is gxx_personality, then I'd say the post by "fortran" is correct.
See my response to this earlier question: When to use extern "C" in simple words?
It should hopefully make it clear how to mix C and C++ code.
How this works in C or C++?
extern "C" {
#include <unistd.h>
#include <fd_config.h>
#include <ut_trace.h>
#include <sys/stat.h>
#include <sys/types.h>
}
The C++ standard does not specify how compilers should name the symbols in their object files (for instance, Foo::bar() might end up as __clsFoo_fncBar or some gobbledygook). The C standard does, and it is almost always different from how C++ compilers do it (C doesn't have to deal with classes, namespaces, overloading, etc.).
As a result, when you are linking against an object file that was output by a C compiler, you have to tell your C++ compiler to look for symbols with names that correspond to the C standard. You are essentially putting it in "C mode." This is what the "C" part of extern "C" does.
(Alternatively, you might also be declaring functions or variables that could be used by an external C object file. In this case, it means export those symbols the C way.)
If your Project has C and C++ source files and you need to build as a whole( C files calls some functions in C++ files) ,so we need to protect the C file function calls and symbols by declaring as in C++ files by
extern "C"
{
/symbols used in c files/
uint8 GetCurrentthreadState(HANDLE ThreadId)
}
Then the C++ complier generate compilation output which is same as that of C complier for the above declared functions and symbols.So on linking time , the compiler can easily link the C and C++ defined symbols with out any link error.
So my opinion is not needed to give the #ifdef __cplusplus check on compilation.
Because we need to protect the symbols in c++ files right? Also C++ files can be compiled by C++ compiler only right?
/renjith g
It will not work, you need to add the cplusplus preprocessor...
#ifdef __cplusplus
extern "C" {
#endif
// your code
#ifdef __cplusplus
}
#endif
EDIT:
In C++, the name will be treated like in C which mean that there will be no mangle name. It allows to make the difference between two C++ different function with different argument type/number or a different namespace in a library (for library purpose libname.so, libname.a). If the name is mangled, the C program will not be able to recognize it
eg:
int myfction()
void myfunction(int)
void myfunction(int, char)
C library: myfction
C++ library: int_myction (it depend on your compiler)
C++ library: int_myction_int (it depend on your compiler)
C++ library: int_myction_int_char (it depend on your compiler)
// ... which is not allowed in C program
Every C++ Compiler needs to support the extern "C" linkage.
The code in such block could be legacy code written in C for a certain functionality, which is required for the current program.
How this is implemented is mostly compiler dependent, However I heard that many Compilers disable the name mangling and change the calling convention.