I am new in the field of Linux system programming.I currently program in C and want to switch to c++.
Can we use all the functions defined in POSIX C libraries in c++ without any change ?
In principle you should be able to use any C API from C++; the language includes features to facilitate it, and most C library authors are aware that people want to do this and will take the appropriate steps. For the system programming interfaces specified by POSIX, C++ compatibility is an explicit design goal.
However, you may still encounter problems. In my experience, the most common problems are:
C API headers often dump hundreds of symbols into the global namespace. Some of those symbols may conflict with C++ library symbols, which will get you in trouble if you using namespace std (but you weren't doing that, right?)
C API headers often make heavy use of macros, including macro names that, yep, might conflict with C++ library symbols; std:: won't save you there.
Compiling your program in a strict conformance mode (e.g. -std=c++11 -D_XOPEN_SOURCE=700) may expose bugs in system headers. This is more likely to happen with C++ than C.
A small handful of the POSIX APIs have abnormal control-flow behavior that may interact poorly with C++ exceptions and destructors, depending on how thorough your C library implementor was about avoiding the problem. setjmp and longjmp are obviously a concern here (has anyone done a C library that implements those on top of DWARF-style exception handling?) but so are fork, setcontext and friends, pthread_cancel, pthread_cleanup_push, and probably a few others I can't remember off the top of my head. (I recall a giant, ultimately inconclusive argument between Ulrich Drepper and the GCC C++ guys back in 2004 or so about exactly how pthread_cancel should behave in the presence of destructors.)
If you go beyond POSIX, you may also have problems with:
Headers that don't bother to wrap all the declarations in an extern "C" block when compiled as C++, which means all the function names get mangled when they shouldn't have been, and the link fails.
Headers that don't even bother to stick to the intersection of C and C++. In the worst case, this can cause failures that don't manifest until the program is run. The most common instances of this are:
Blithely using some C++ keyword as a declared-name (e.g. int template;)
Assuming that void * is assignment compatible with other pointer types (e.g. that it is not necessary to cast the result of malloc)
Assuming that struct foo; does not define a typedef-name foo
Note that the headers specified by POSIX frequently contain system-specific extensions that have not been as carefully thought out as the POSIX interfaces themselves.
"Can we use all the functions defined in POSIX C libraries in c++ without any change ?"
Of course you can. Any c-style API can be used seamlessly in c++.
Related
I have previously written C++ code that #includes Unix and Linux API headers and these programs have produced the expected behavior. That said, I don't know if this can be relied on. It's possible that incompatibilities between C and C++ could cause valid C headers to act in unexpected ways when used by C++ programs.
Can Unix and Linux API headers reliably be used by code that will be compiled as C++?
Is this a goal of the authors of those headers? Or are those headers only intended to be valid C?
Are there any known pitfalls when doing this?
Obviously the Unix and Linux distributions are numerous and I don't expect an answer to address every distribution one by one. My expectation is that the same answer will apply to almost all distributions of Unix and Linux and exceptions will prove the rule. If this assumption is wrong, an explanation of that would also be a valid answer.
By Unix headers I mean these:
http://www.unix.org/version3/apis/headers.html
By Linux headers I mean the headers provided by Linux distributions usually as a package named "linux-headers" that allow programs to interact with the Linux kernel. For example, this Debian package:
https://packages.debian.org/wheezy/kernel/linux-headers-3.2.0-4-amd64
I realize the Unix link is only a specification and that each Linux distribution is different but again I suspect it's reasonable to ask this question for most distributions. If that's not true then correct me.
Edit I only mean to refer to headers used by user space programs.
C standard headers like <stdio.h>, <stdlib.h>, and so forth are specified in Appendix D of the C++ standard, which states:
These are deprecated features, where deprecated is defined as:
Normative for the current edition of the Standard, but not guaranteed
to be part of the Standard in future revisions.
The non-deprecated C++ versions of the C standard headers have names like <cstdio>, <cstdlib>, etc., and they technically put their definitions into the std (not global) namespace. So, to be 100% compliant with the non-deprecated part of the C++ spec, you need to write something like this:
#include <cstdio>
int main() {
std::printf("Hello, world!\n");
}
That said, to my knowledge, no existing implementation actually forces you to do this, and in my opinion it is unlikely any ever will. So in practice, you can safely use C standard headers in C++ without much concern.
Also, if you are on (e.g.) a POSIX system, you can generally use POSIX functionality from C++ equally safely. Certainly nobody is going to deliberately break any of this because users would revolt.
However, accidental breakage is conceivable when mixing paradigms. If both the platform and the language standard provide some feature, you should use one or the other but not both. In particular, I would not mix POSIX threading and synchronization mechanisms with standard C++11 threading and synchronization mechanisms, because it is easy to imagine an optimizer knowing too much about the latter and generating code incompatible with the former.
[Update, to elaborate somewhat]
<unistd.h> is an example of what I mean about platform-dependent functionality. It will generally work fine from C++, and neither the library nor the compiler developers will break it gratuitiously because that would be too annoying. So go ahead and call getpid() or pipe() or whatever.
But be aware that mixing paradigms raises all sorts of questions. To name just a few off the top of my head:
Can you call new from a signal handler?
Can you use dup2 onto descriptor 0 to redirect cin?
What POSIX functions can you call safely during static initialization (i.e. before main executes)?
These questions and others like them are not addressed by any spec. The answers depend on your specific implementation and could change between releases.
Having said all that... Just about every non-trivial C++ program relies on platform-specific functionality exposed by some C interface. So what you are describing will work fine in practice provided you (a) have some idea what is going on "under the hood"; (b) have reasonable expectations; and (c) do not attempt to mix standard and platform-specific paradigms.
1) Yes: "standard headers" are standard. You can safely use them regardless of platform.
2) Yes: you can mix C headers (e.g. <stdio.h>) with C++ headers (e.g. <iostream>) in the same C++ translation unit.
3) NO: you should NOT use linux kernel headers in a user mode program, nor vice versa.
Linux kernel headers are intended for kernel-mode drivers, not for "normal", user space applications.
Here is a bit more information:
https://unix.stackexchange.com/questions/27042/what-does-a-kernel-source-tree-contain-is-this-related-to-linux-kernel-headers
http://kernelnewbies.org/KernelHeaders
I have searched the net without any conclusive answers to issue related to lack of C++ ABI when it comes to exporting c++ classes accross dll boundaries in windows.
I can use extern c and provide a c like api to a library , but I would like end users to be able to use classes that us stl containers.
What generic patterns do you use for exporting a class that uses stl container across dll boundaries , in a safe manner? e.g. best practice.
This question is for experienced library authors.
Regards
Niladri
There's no defined C++ ABI and it does differ between compilers in terms of memory layout, name mangling, RTL etc.
It gets worse than that though. If you are targeting MSVC compiler for example, your dll/exe can be built with different macros that configure the STL to not include iterator checks so that it is faster. This modifies the layout of STL classes and you end up breaking the One Definition Rule (ODR) when you link (but the link still succeeds). If the ODR is violated then your program will crash seemingly randomly.
I would recommend maybe reading Imperfect C++ which has a chapter on the subject of C++ ABIs.
The upshot is that either:
you compile the dll specifically for the target compiler that is going to link to it and name the dll's appropriately (like boost does it). In this case you can't avoid ODR violations so the user of the library must be able to recompile the library themselves with different options.
Provide a portable C API and provide C++ wrapper classes for convenience that are compiled on the client side of the API. This is time consuming but portable.
Take a look at CppComponents https://github.com/jbandela/cppcomponents
You can export classes and interfaces across dll boundaries even across different compilers.
The library is header-only so nothing to build. To use it, you will need MSVC 2013 and/or GCC 4.8 as it uses C++11 variadic templates extensively.
See presentation from C++Now
https://github.com/boostcon/cppnow_presentations_2014/blob/master/files/cppnow2014_bandela_presentation.pdf?raw=true
https://github.com/jbandela/cppcomponents_cppnow_examples has the examples from the presentation.
I have a library I'm building which is targeted to be a DLL that is linked into the main solution.
This new DLL is quite complex and I'd like to make use of C++11 features, while the program that will link it most certainly does not. In fact, the main program is currently "cleanly" built using VS2008 and VS2010 (and i think GCC 4.3 for linux?).
What I propose:
Using VS2012 as the IDE and Intel C++ Compiler 2013 for compilation to .dll/.so - for linux - which, as I understand, is basically down to machine form (like an .exe).
While I'm familiar with using C++ to solve problems, I am not fluent in the fundamentals of compilation/linking, etc. Therefore, I'd like to ask the community if
This is possible
If it is possible, how easy is it (as simple as I described?) / what pitfalls or issues can I expect along the way (is it worth it)?
Areas of concern I anticipate:
runtime libraries - I expect this to be the factor that derails this effort. I know nothing about them/how they work except that they might be a problem.
Standard Library implementation differences - should it matter if it's down to DLL form?
threading conflicts - the dll threads and the main programs threads never modify the same data, and actually one of the main program's threads will call the DLL functions.
Bonus: While the above is the route I expect to take, I'd ideally like to have this code open for intellisense, general viewing, etc (essentially for it to become a project in the main solution). Is there a way to specify different runtime libraries/compiler? Can this be done?
EDIT: The main reason for this bonus part is to eliminate the necessary "versioning" conflicts that will arise if the main program and this library are built separately.
NOTE: I'm not using C++11 just for the sake of being newer - strongly typed enums and cross-platform threading code will be huge bonuses for the library.
The question isn't so much "Can an application use a library built with a different compiler ?" (The answer is yes.) but "What C++ features can be used in the public interface of a library built with another compiler and C++ standard library?"
On Windows, the answer is "almost none". Interfaces (classes containing only virtual functions) are about it. No classes with data members. No exceptions. No runtime objects (like iostream instances or strings). No templates.
On Linux, the answer is "lots more but still not many". Classes are ok, as long as the ODR is satisfied. Exceptions will work. Templates too, as long as the definition is exactly the same on both sides. But definitions of standard library types did change between C++03 and C++11, so you won't for example be able to pass std::string or std::vector<int> objects between the application and library (both sides can use these features, but the same object can't cross over).
I'm afraid this is not possible with C++. Especially name mangling can be different. All C++ files linked together need to be compiled with same compiler.
In C++, extern "C" stuff is standard (naming, calling convention), so C libraries can be called from C++, as well as C++ functions declared withing extern "C" block. This exludes classes, templates, overloads, mixing them compiled by different compilers is not workable.
Which is a pity.
I have cross compiled an open-source library (C++ based) using my G++ cross compiler. I am now trying to use the outputted .a files in my C based application that is built using my GCC compiler... Is that possible?
Yes. Ensure that all functions you want to use are extern "C" and that you only use basic types on the functions you want to use.
If you use the same version GCC as you use G++ it should definitely not be any problem. Cross-version should be ok, but may have very minor incompatibilities. New GCC (3.0+) conform to the Itanium ABI so they'll be fine; they have a binary agreement on how to exchange & format data.
You will need to ensure that the C++ functions called from the C code are declared extern "C" and that their interfaces use only types that can be handled by C (simple types, opaque pointers, etc).
You will probably also need to link the application with the C++ compiler, rather than the C compiler, to ensure that the correct initializations are done for the C++ library. The C++ compiler used for the linking must be 'the same' as the one used to generate the library. That means either the same version of the C++ compiler or a compatible version of it. It usually means that you cannot link with CompilerA (from Vendor A) if the library was produced by CompilerB (from Vendor B); the C++ runtime conventions are such that different compilers (deliberately) use different schemes for supporting different features of C++.
You can link a C application to a c++ library,
BUT you can only include header files containing valid C -- not C++ -- code,
AND any c++ functions you call must have been declared with the extern "C" declaration.
The answer to your question is "yes" but as others have pointed out, there are some considerations, hazards & limitations to what you can do & how you do it.
Just recently in the course of covering this same topic with a client, I came across an article with a pretty good treatment of the topic. The article discusses things like calling C code from C++ code, calling C++ code from C code, linker considerations, function wrappers, exceptions, linkage specifications, and accessing C++ classes from C, etc.
Article: Mixing C and C++ Code in the Same Program
If the C++ library has C++ interfaces you cannot use them directly, you will have to create wrappers that are compiled as C++ but which have extern "C" linkage. The complexity of such wrappers will depend on the natuire of the interfaces, use of C++-only features such as classes, and function/operator overloading will require work to map an OO interface to a procedural one.
The easiest, least-hassle method to do this, assuming your C code is reasonably sane, is to simply build your C application with g++.
Remember, good C code almost always builds in a C++ compiler. Then there are no special considerations, no extern "C" statements to add, no ABI issues, etc, and you can easily use the C++ library to its fullest, regardless of how its functions are declared.
Each header from the C Standard
Library is included in the C++
Standard Library under a different
name, generated by removing the .h,
and adding a 'c' at the start, for
example 'time.h' becomes 'ctime'. The
only difference between these headers
and the traditional C Standard Library
headers is that where possible the
functions should be placed into the
std:: namespace (although few
compilers actually do this).
Since c functions are put into the std:: namespace,I tried :
man std::printf
but got :
No manual entry for std:printf
Any reasons?(I've installed libstdc++-doc and I've no problem with canonical c++ stuff like man std::cout)
UPDATE
The reason to say c++ is junky at least includes:
junky c++ manual
an empty c++ programe needs libstdc++,libm and libgcc_s,while c programe only needs libc.
There really is no point in documenting the C++ functions that come from standard C if they are identical and are already documented (like printf is).
The behavior of the C standard library functions is out of the control of libstdc++ developers. It relies (in this and most other C++ Standard library implementations) on the underlying platform's Libc implementation. On Linux, that's most probably glibc, on Windows, msvcrt, etc...
The point is that all these different libraries provide different and non-conforming behavior, which would have to be documented in the libstdc++ documentation, and that is impossible (no, very hard) to do and maintain. It also serves no practical purpose, as this documentation exists elsewhere.