include C headers in C++ as noexcept - c++

Is there a way (compiler extensions are acceptable) to include C headers and mark included C functions as noexcept, but without modifying headers?
For example, I have a C library and its header header.h. No C++ callback will be passed into it so it never throws. Can I mark the included C functions as noexcept or tell compiler that they never throw, so that the compiler doesn't have to generate unused code and enable some possible optimizations for callers? Note that the C++ code using the C library should still be able to use exceptions (so disabling exceptions for the entire program is not an option).
extern "C" {
#include "header.h" // Is there a way to mark included C functions here as noexcept?
}

There isn't a way that you're looking for.
What you could do for example, is not use the header at all. Write your own header where the functions are marked noexcept. This of course has the drawback that you must maintain the new header and keep it up to date with changes in the library.
Or - if you can give up the premise of not modifying the header - you can add noexcept to the header while still keeping it compatible with C by wrapping the C++ features in macros. This is how for example C standard libraries are written, as they are inherited by C++ standard libraries.

Related

How can I include a C header that uses a C++ keyword as an identifier in C++?

I've been using C++ and compiling with clang++. I would like to include the <xcb/xkb.h> header for an X11 program I am writing.
Unfortunately this header uses explicit for some field names (such as line 727) and that is a keyword in C++.
Is there anyway to deal with this?
xcb/xkb.h:
// ...
#ifdef __cplusplus
extern "C" {
#endif
// ...
typedef struct xcb_xkb_set_explicit_t {
xcb_keycode_t keycode;
uint8_t explicit;
} xcb_xkb_set_explicit_t;
// ...
#ifdef __cplusplus
}
#endif
// ...
Use a macro to rename the fields:
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wkeyword-macro"
#endif
#define explicit explicit_
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#include <xcb/xkb.h>
#undef explicit
Using a keyword as a macro name is ill-formed in standard C++, but GCC, Clang (with pragma), and MSVC do accept it. (The standard says you "shall not" do it, cppreference clarifies that it means "ill-formed".)
How can I include a C header that uses a C++ keyword as an identifier in C++?
There is no standard-conforming solution to be able to include such header. In order to be able to include a header in C++, it must be written in valid C++. In case of a C header, it would thus have to be written in common subset of C and C++.
The ideal solution is to fix the header to be valid C++. A standard-conforming workaround is to write a C++ conforming wrapper in C.
(Not an answer to the exact question, but possibly useful for the general problem of interfacing C & C++)
How about using an intermediate set of C files (.c & .h) to wrap the incompatible header and provide a C++-compatible interface to the rest of your program? If that interface is high-level enough, then you would only need to include the incompatible header file in the wrapper .c file only, allowing the wrapper .h header file to be included in C++ code normally.
Depending on the details, you might end up doing some trivial copying of data, but the resulting C interface might be much more suited to your specific needs.
One solution is to add a generation step to your makefile that copies the header and renames the field, and include said autogenerated header instead.
(This is between difficult to impossible to do in the general case, but in this case given that the header isn't likely using explicit for anything else even just a simple (gnu) sed (s/\bexplicit\b/explicit_field/g or somesuch) would work. The trickier bit is figuring out the correct file to copy.)
Make sure that the location of the copied header is before the original header in your include path, in case something else in your includes indirectly includes the header.
Just changing a field name shouldn't have any effects on e.g. ABI, at least for a nominally-C-compatible header. (There are cases in C++ where renaming a field does affect things.)

Standard C++ way of calling C standard library functions

I have a few questions about calling C standard library functions in C++:
If I want to call getline() which is declared in <stdio.h> is it always sufficient to just include <cstdio>? This works with the compiler I'm using and I see that it includes <stdio.h> in <cstdio> but I want to know if the standard guarantees this.
Are all C standard library functions guaranteed to be available in C++? With the getline() example from above I noticed that on cppreference under <cstdio> it doesn't list getline().
For C standard library functions and types that are made available in the std:: namespace like FILE or malloc() are they any problems with accessing them through the global namespace or is it just more idiomatic to access them as std::FILE or std::malloc()?
You should always include what the documentation tells you to. (C++ standard library implementations will often be written such that functions are reachable via other includes but of course relying on that means your code is not portable.) Note that there is no standard getline function in C. But there is one in C++:
std::getline()
is defined in header <string>. The C++ standard doesn't guarantee that, in general, C functions are available at global scope or are even part of the C++ standard library. The two languages began their divergence many years ago and so the idea that C++ is in a sense a superset of C - libraries included - is a myth.
Reference: https://en.cppreference.com/w/cpp/string/basic_string/getline
In relation to #3:
The .h libraries must place all its names in the global namespace and may also place them in the std:: namespace.
The c begining version must place all its names in the std:: namespace and may also place them in the global namespace.
It should be easy to link any C library with C++ in general, not just the standard headers.
Note that you may have to trawl through man to work out what version of what unix the method was introduced or if it is a specific extension, and decide for yourself if that historical startpoint is acceptable to you. But this is true if you wrote a C program instead of C++.
The C++ alias headers include most, but not all of the functionality from the C headers, but occasionally you may find the only way to get a function is to include the C header directly. On the other hand you need to ask yourself why they chose not to include that method, usually because it is deprecated, dangerous, or non-standard.
So the way it works, is that C functions, including C library functions are introduced with the extern "C" keyword.
When you #include C header files they will generally contain some code such as:
/* C++ needs to know that types and declarations are C, not C++. */
#ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# define __END_DECLS }
#else
# define __BEGIN_DECLS
# define __END_DECLS
#endif
__BEGIN_DECLS
... which introduces a section of C interface functions.
If you needed to include a really old C library that did not do this, then you could easily add extern "C" around the #include:
extern "C" {
#include "ancientinterface.h"
};
You can also write your own methods that are "C" interface compatible.

GCC: header only C-wrapper around a C++ template function (no linker requirements)

My Problem is that I want to call some template function in C.
Therefore, I have declared an extern "C" function as a wrapper function, which calls this template function.
I know, that I need to compile the wrapper function, with the c++ compiler and then I get an object file, which I can link against a normal c-program.
The problem is, that I have written a header only C++ library, which I want to use in C, but in C I can't make the library header only anymore, once I need to link the C-program against the wrapper function.
So does there exist any way of generating a header only c-library, which calls the c++ template function? This method should work in GCC and it is absolutely no problem, if it is nonstandard, requires several pragmas, cli-parameters or something else.
I think, a possible solution would be to call gcc in C-mode on a file, where on a particular line, a switch from C to C++ inside the header file is possible. This C++ switch does the actual template call and than a switch back to the C-compiler is performed. Does some method exist?
e.g. like this:
#include <iostream>
#define SWITCH_TO_CPP_COMPILER() /*TODO: is this possible?*/
#define SWITCH_BACK_TO_C_COMPILER() /*TODO: is this possible?*/
#ifdef __cplusplus
extern "C" {
#endif
inline bool wrapper();
#ifdef __cplusplus
}
#endif
SWITCH_TO_CPP_COMPILER();
template<bool tmp>
constexpr bool template_func() noexcept {
return tmp;
}
inline bool wrapper() {
return template_func<true>();
}
SWITCH_BACK_TO_C_COMPILER()
#include <stdio.h>
int main() {
printf("%d\n", wrapper());
}
I have already looked at several questions, but they do not answer it:
C Wrapper for C++: How to deal with C++ templates?
how to write c wrapper around c++ code to expose class methods
Create a C wrapper around a C++ library that can be linked by a C linker
C wrapper around C++ library without unnecessary header files
The whole point of the C wrapper is to have the C++ compiler generate an object module for the instantiated template and the wrapper, and letting the C compiler be blissfully unaware of anything but the wrapper, known/invoked thorough an extern function declaration.
This thing cannot be header-only: a header is brutally included in the file that uses it, and that file is going to be processed by a C compiler, which then would have to be able to parse/instantiate the C++ template besides the wrapper function, and this is obviously not possible. Parsing C++ is already complex as it is, requiring to switch to a different language in mid-air is completely bonkers.
If you want to use your library into a "C proper" program you have to have an extra TU compiled by a C++ compiler. Otherwise, since however you think about this you need some C++ compiler being able to compile your template, just compile everything in C++ and, if you prefer, just use the C subset for the rest of the files.
You already have a dependency from a C++ compiler and most probably from the C++ standard library, so this isn't going to change much besides compilation speed in the grand scheme of things.
This in mind what Matteo wrote in his answer:
Convinced that what OP wants is impossible, I tried to find a substantive argument.
I compared the "Phases of translation" for C and C++.
The first phases concerning pre-processing look quite similar but starting with phase 7 (compilation) it becomes quite different.
I hardly doubt that any compiler can switch from C to C++ and back in the mid of a translation unit (if it is standard conform).

How to link old C code with reserved keywords in it with C++?

I have a 10+ years old C library which -- I believe -- used to work just fine in the good old days, but when I tried to use it with a C++ source (containing the main function) the other day I ran into some difficulties.
Edit: to clarify, the C library compiles just fine with gcc, and it generates an object file old_c_library.o. This library was supposed to be used in a way so that the C header file old_c_library.h is #included in your main.c C source file. Then your main C source file should be compiled and linked together with old_c_library.o via gcc. Here I want to use a C++ source file main.cpp instead, and compile/link it with g++.
The following three problems occurred, during the compilation of the C++ source file:
one of the header files of the C library contains the C++ reserved word new (it is the name of an integer), which resulted in fatal error; and
one of the header files of the C library contains a calloc call (an explicit typecast is missing), which resulted in fatal error; and
various files of the C library contain code where comparison of signed and unsigned integers happen, which resulted in warnings.
Edit: I tried to use the #extern "C" { #include "obsolete_c_library.h" } "trick", as suggested in the comments, but that did not solve any of my problems.
I can sort out problem 1 by renaming all instances of the reserved words and replacing them by -- basically -- anything else. I can sort out problem 2 by typecasting the calloc call. I might try to sort out the warnings by ideas suggested here: How to disable GCC warnings for a few lines of code.
But I still wonder, is there a way to overcome these difficulties in an elegant, high-level way, without actually touching the original library?
Relevant:
Where is C not a subset of C++? and Do I cast the result of malloc? and How do I use extern to share variables between source files?.
Generally speaking, it is not safe to #include C header files into C++ sources if those headers were not built in anticipation of such usage. Under some circumstances it can be made to work, but you need to be prepared to either modify the headers or write your own declarations for the functions and global variables you want to access.
At minimum, if the C headers declare any functions and you are not recompiling those functions in C++ then you must ensure that the declarations are assigned C linkage in your C++ code. It's not uncommon for C headers to account for that automatically via conditional compilation directives, but if they do not then you can do it on the other side by wrapping the inclusion(s) in a C linkage block:
extern "C" {
#include "myclib.h"
}
If the C headers declare globals whose names conflict with C++ keywords, and which you do not need to reference, then you may be able to use the preprocessor to redefine them:
#define new extern_new
#include "myclib.h"
#undef new
That's not guaranteed to work, but it's worth a try. Do not forget to #undef such macros after including the C headers, as shown.
There may be other fun tricks you can play with macros to adapt specific headers to C++, but at some point it makes more sense to just copy / rewrite the needed declarations (and only those), either in your main C++ source or in your own C++ header. Note that doing so does not remove the need to declare C linkage -- that requirement comes from the library having been compiled by a C compiler rather than a C++ compiler.
You can write a duplicate of the c header with the only difference being lack of declaration of extern int new. Then use the newly created c++ friendly header instead of the old, incompatible one.
If you need to refer that variable from c++, then you need to do something more complex. You will need to write a new wrapper library in c, that exposes read and write functions a pointer to c++ that can be used to access the unfortunately named variable.
If some inline functions refer to the variable, then you can leave those out from the duplicate header and if you need to call them from c++, re-implement them in a c++ friendly manner. Just don't give the re-implementation same name within extern "C", because that would give you a conflict with the original inline function possibly used by some existing c code.
Do the same header duplication as described in 1. leaving out the problematic inline function and re-implementing if needed.
Warnings can be ignored or disabled as you already know. No need to modify the original headers. You could rewrite any {const,type}-unsafe inline functions with versions that don't generate warnings, but you have to consider whether your time is worth it.
The disadvantage of this approach is that you now have two vesions of some/all of the headers. New ones used by c++, and the old ones that may be used by some old code.
If you can give up the requirement of not touching the original library and don't need to work with an existing compiled binary, then an elegant solution would be to simply rename the problematic variables (1.). Make non-c++-compatible inline functions (2.) non-inline and move them into c source files. Fix unsafe code (3.) that generates warnings or if the warning is c++ specific, simply make the function non-inline.

Header-only linking

Many C++ projects (e.g. many Boost libraries) are "header-only linked".
Is this possible also in plain C? How to put the source code into headers? Are there any sites about it?
Executive summary: You can, but you shouldn't.
C and C++ code is preprocessed before it's compiled: all headers are "pasted" into the source files that include them, recursively. If you define a function in a header and it is included by two C files, you will end up with two copies in each object file (One Definition Rule violation).
You can create "header-only" C libraries if all your functions are marked as static, that is, not visible outside the translation unit. But it also means you will get a copy of all the static functions in each translation unit that includes the header file.
It is a bit different in C++: inline functions are not static, symbols emitted by the compiler are still visible by the linker, but the linker can discard duplicates, rather than giving up ("weak" symbols).
It's not idiomatic to write C code in the headers, unless it's based on macros (e.g. queue(3)). In C++, the main reason to keep code in the headers are templates, which may result in code instantiation for different template parameters, which is not applicable to C.
You do not link headers.
In C++ it's slightly easier to write code that's already better-off in headers than in separately-compiled modules because templates require it. 1
But you can also use the inline keyword for functions, which exists in C as well as C++. 2
// Won't cause redefinition link errors, because of 6.7.4/5
inline void foo(void) {
// ...
}
[c99: 6.7.4/5:] A function declared with an inline function
specifier is an inline function. The function specifier may appear
more than once; the behavior is the same as if it appeared only once.
Making a function an inline function suggests that calls to the
function be as fast as possible. The extent to which such
suggestions are effective is implementation-defined.
You're a bit stuck when it comes to data objects, though.
1 - Sort of.
2 - C99 for sure. C89/C90 I'd have to check.
Boost makes heavy use templates and template meta-programming which you cannot emulate (all that easily) in C.
But you can of course cheat by having declarations and code in C headers which you #include but that is not the same thing. I'd say "When in Rome..." and program C as per C conventions with libraries.
Yes, it is quite possible. Declare all functions in headers and either all as static or just use a single compilation unit (i.e. only a single c file) in your projects.
As a personal anecdote, I know quite a number of physicists who insist that this technique is the only true way to program C. It is beneficial because it's the poor man's version of -fwhole-program, i.e. makes optimizations based on the knowledge of function behaviour possible. It is practical because you don't need to learn about using the linker flags. It is a bad idea because your whole program must be compiled as a whole and recompiled with each minor change.
Personally, I'd recommend to let it be or at least go with static for only a few functions.