Which C++ Standard Library Wrapper Functions Do You Use

Can functions from the C standard library be used in C++?

Yes, C++ was originally designed so that any C library can be easily used in C++. Of course this is slightly less true (in particular, if a C library happens to use some C++ keyword like try or dynamic_cast, it won't work; also, if a callback coded in C++ passed to a C library is raising some exception, you are likely to have a big mess).

The standard practice to use a C header file in C++ is

 extern "C" {
#include <some_c_header_file.h>
};

and most existing C header files are designed to cooperate with C++ by actually containing stuff like

 #ifdef __cplusplus
extern "C" {
#endif

//// most of the header material goes here, C style

#ifdef __cplusplus
}; // end extern "C"
#endif

In practice, many C standard headers have equivalent C++ headers wrapping things like above (and also in namespace std). Eg C <stdio.h> is C++ <cstdio> -but you often should prefer genuine C++ streams (<iostream>), however printf-like routines are usually more localization friendly mixed with gettext(3).

However C and C++ are very different languages. You should code in idiomatic C++11 (using standard C++ containers, auto, closures, RAII, smart pointers, rule of five, SFINAE, exceptions, anonymous functions, ...)

Some standard C functions are not very useful in idiomatic C++. For example, you are unlikely to use directly malloc in genuine C++ (at least prefer new -which is still very low level and no more in the C++ spirit-, more likely use a lot the containers and the smart pointers without dealing manually with heap allocation). But POSIX functions (notably syscalls(2) ....) are quite useful in C++. longjmp is likely to be incompatible with C++ exceptions.

BTW, C++ has evolved a lot in this century. Don't learn C++98 but at least C++11 (there are tremendous differences between them) and perhaps C++14. Use a recent compiler (GCC or Clang/LLVM); in december 2015, that means GCC 5 at least or Clang/LLVM 3.7 at least. Don't forget to enable all warnings & debug info in the compiler (e.g. g++ -Wall -Wextra -g -std=c++11)

C++ (that means C++11 at least) is a difficult programming language, considerably more complex than C is. You'll need weeks of reading to learn some of it, and good coding style and discipline is essential (you can easily write very crappy code in C++). Start with Programming: Principles & Practice Using C++

I believe that if you only know C, reading SICP (and studying a bit of Scheme) before learning C++ is worthwhile.

The notion of undefined behavior is very important, both in C and probably even more in C++. You absolutely need to understand it (see C.Lattner's blog on it) and avoid it.

You will also learn a big lot by studying (and perhaps contributing to) some existing free software and its source code. Hence I recommend using Linux.

Reason to use Qt standard library function wrappers

These methods are part of Qt's efforts for platform-independence. Qt tries to hide platform differences and use the best each platform has to offer, replicating that functionality on platforms where it is not available. Here is what the documentation of qstrncpy has to say:

A safe strncpy() function.

Copies at most len bytes from src (stopping at len or the terminating '\0' whichever comes first) into dst and returns a pointer to dst. Guarantees that dst is '\0'-terminated. If src or dst is nullptr, returns nullptr immediately.

[…]

Note: When compiling with Visual C++ compiler version 14.00 (Visual C++ 2005) or later, internally the function strncpy_s will be used.

So qstrncpy is safer than strncpy.

C/C++ standard library wrapper with exceptions

Maybe the question wasn't clear,
btw i've found this library is exactly what i was looking for:
commonc++.

Edit: Better alternative still maintained.

Inner working of the C standard library

A good starting point would be POSIX. The POSIX 2008 specification is available online here:

http://pubs.opengroup.org/onlinepubs/9699919799/

It's more accessible (but sometimes less rigorous) than the C standard, and covers a lot more than just the C standard, i.e. most of the standardized parts of Unix-like systems' standard libraries.

If you're interested in implementations, the first thing to be aware of is that the POSIX-described behavior is usually split (by necessity and pragmatic reasons) between the kernel implementation and the userspace libc implementation. A large number of the functions in POSIX (and a few from the C standard) will merely be wrappers for "system calls", i.e. transitions into kernelspace to service the request. On some libc implementations, even finding these wrappers will be difficult, since they're often either automatically generated by the build scripts, and/or unified into a single assembly-language file.

The major (significant amount of non-kernel code) subsystems of the standard library are generally:

  • stdio: On glibc, this is implemented by the GNU libio library, which is a unified implementation of C stdio and C++ iostream, optimized so that neither has to be slowed down by being a wrapper for the other. It's a big hack, and the code is difficult to find and follow. Other implementations (especially the BSDs, but also other libcs on Linux) are much simpler and clearer to read. Ultimately they're based on the underlying file-descriptor IO functions like open, read, etc.
  • POSIX threads: On glibc and modern uClibc, this is NPTL. I'm not familiar with the BSDs' thread implementations. Other Linux libcs either lack threads or provide their own implementations based mainly on Linux clone and futex syscalls.
  • Math library: ultimately, almost all of these are based on the old Sun math code from the early 90s, but they've diverged a lot. Fdlibm is a pretty good base approximation of the code used in modern libcs.
  • User, group, hostname (DNS), etc. lookups: This is handled through libnss in glibc, and directly in most other libcs.
  • Regular expression and glob matching
  • Time and timezone handling
  • Locale and charset conversion
  • Malloc

If you want to get started reading sources, I would recommend not starting with glibc. It's very large and unwieldy. If you do want to read glibc, be aware that lots of the code is hiding under the sysdeps trees and is organized based on the diversity of systems it's applicable to.

Dietlibc is quite readable, but if you read its source, be aware that it's full of common C programming mistakes (e.g. using int where size_t is needed, not checking for overflows, etc.). If you keep this in mind, it might not be a bad choice, since ignoring lots of possible errors/failures tends to make the code very simple.

With that said, for reading libc source, I would most recommend either one of the BSDs or musl (disclaimer: I am the primary author of musl so I am a bit biased here). BSDs also have the advantage that the kernelspace code is also extremely simple and readable, so if you want to read the kernel code on the other side of a system call, you can do that too.

Which C++20 standard library containers have a .at member access function?

I ended up grepping libstdc++ include directory for \bat( and that has given me:

std::basic_string
std::basic_string_view
std::array
std::vector
std::vector<bool>
std::unordered_map
std::map
std::dequeue

I'm not sure if this is exhaustive.

There is also rope and vstring but I don't think these are standard.

How should I wrap C libraries into C++

The first approach is the more C++ way of doing things. All the functions are grouped together into one logical unit (the class), you've encapsulated the data so that RAII prevents resource leaks and you've managed to drop the foo_ prefix, too!

Write C wrapper for C++ libraries?

An issue with this is, if you want to write C wrappers which call Boost functions, what do you do if an exception is thrown? You basically have to swallow it in the caller before it reaches C, but its a bit awkward to properly report it to C then and there are quite a few types of exceptions.

Usually people use C instead of C++ when they specifically want the extra portability or cannot provide all the C++ dependencies for some reason. If you want to write a C program that uses boost::filesystem, why not just compile it as C++? You will have a lot less exception handling boiler plate code to write, and less can go wrong.

Writing a C++ wrapper for a C library

A C++ wrapper is not required - you can simply call the C functions from your C++ code. IMHO, it's best not to wrap C code - if you want to turn it into C++ code - fine, but do a complete re-write.

Practically, assuming your C functions are declared in a file called myfuncs.h then in your C++ code you will want to include them like this:

extern "C" {
#include "myfuncs.h"
}

in order to give them C linkage when compiled with the C++ compiler.



Related Topics



Leave a reply



Submit