C/C++ linkage convention - c++

When calling C++ algorithms like copy_if, transform etc which take a unary or binary function as the last argument, can I pass a C library function like atoi or tolower.
For e.g. below calls work fine and give the correct output (tried in ideone)
1) transform (foo, foo+5, bar, atoi);
2) transform (foo, foo+5, bar, ptr_fun(atoi));
3) transform(s.begin(),s.end(),s.begin(), static_cast<int (*)(int)>(tolower));
Is this usage guaranteed to work with all C++ compilers ?
The book thinking in C++ mentions "This works with some compilers, but it is not required to." The reason mentioned is (as I understand it) transform is C++ function and expects its last argument to have same calling convention.
The book also suggests a solution for this problem which is to create a wrapper function like this in a separate cpp file and do not include iostreams header file.
// tolower_wrapper.cpp
string strTolower(string s) {
transform(s.begin(), s.end(), s.begin(), tolower);
return s;
}
This works fine, but I did not understand how this resolves the calling convention issue ?
transform is still a c++ function and tolower is still a C function in the strTolower, so how this different calling conventions are handled here.

The first thing to note, which is not actually part of your question but which might help explain for someone reading this, is that the algorithms can take either a function pointer or a function object as an argument.
A function pointer is just that - a pointer to a function which expects to take a specific set of parameters and return a specific type.
A function object is an instance of a class which has overridden operator().
When expanding the algorithm template, the compiler will be able to see which of the two cases applies and will generate appropriate calling code.
In the case of a C function being used as a binary function in an algorithm, it is a function pointer that you are supplying. You can call a C function from C++, as long as it is declared extern C { ... }.
Many compilers come with header files for the C library functions which include something like this:
#ifdef __cplusplus
extern "C" {
#endif
/* function declarations here */
#ifdef __cplusplus
}
#endif
so that if you include a C library header from a C++ program, the contained functions will all be magically available to you. That part, however, is not guaranteed by the standard, which is why your book states it may not work with all compilers.
Another wrinkle is that you are not allowed to cast function pointers to a type with a different language linkage, which in at least some of your examples you are doing, although some compilers do seem to allow that anyway - for example see this GCC Bug.
The other catch, which applies specifically to tolower for example, is that some of the names of C library functions are also names of functions or templates in the C++ std library. For example, the name tolower is also defined in <locale>. This specific case is discussed in this GCC bug report. The use of a wrapper, compiled in a separate compilation unit which does not include the conflicting declarations, would resolve this issue.

Related

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).

NASM call for external C++ function

I am trying to call external C++ function from NASM. As I was searching on google I did not find any related solution.
C++
void kernel_main()
{
char* vidmem = (char*)0xb8000;
/* And so on... */
}
NASM
;Some calls before
section .text
;nothing special here
global start
extern kernel_main ;our problem
After running compiling these two files I am getting this error: kernel.asm(.text+0xe): undefined reference to kernel_main'
What is wrong here? Thanks.
There is no standardized method of calling C++ functions from assembly, as of now. This is due to a feature called name-mangling. The C++ compiler toolchain does not emit symbols with the names exactly written in the code. Therefore, you don't know what the name will be for the symbol representing the function coded with the name kernel_main or kernelMain, whatever.
Why is name-mangling required?
You can declare multiple entities (classes, functions, methods, namespaces, etc.) with the same name in C++, but under different parent namespaces. This causes symbol conflicts if two entities with the name local name (e.g. local name of class SomeContainer in namespace SymbolDomain is SomeContainer but global name is SymbolDomain::SomeContainer, atleast to talk in this answer, okay) have the same symbol name.
Conflicts also occur with method overloading, therefore, the types of each argument are also emitted (in some form) for methods of classes. To cope with this, the C++ toolchain will somehow mangle the actual names in the ELF binary object.
So, can't I use the C++ mangled name in assembly?
Yes, this is one solution. You can use readelf -s fileName with the object-file for kernel_main. You'll have to search for a symbol having some similarity with kernel_main. Once you think you got it, then confirm that with echo _ZnSymbolName | c++filt which should output kernel_main.
You use this name in assembly instead of kernel_main.
The problem with this solution is that, if for some reason, you change the arguments, return value, or anything else (we don't know what affects name-mangling), your assembly code may break. Therefore, you have to be careful about this. On the other hand, this is not a good practice, as your going into non-standard stuff.
Note that name-mangling is not standardized, and varies from toolchain to toolchain. By depending on it, your sticking to the same compiler too.
Can't I do something standardized?
Yep. You could use a C function in C++ by declaring the function extern "C" like this
extern "C" void kernelMain(void);
This is the best solution in your case, as your kernel_main is already a C-style function with no parent class and namespace. Note that, the C function is written in C++ and still uses C++ features (internally).
Other solutions include using a macro indirection, where a C function calls the C++ function, if you really need to. Something like this -
///
/// Simple class containing a method to illustrate the concept of
/// indirection.
///
class SomeContainer
{
public:
int execute(int y)
{
}
}
#define _SepArg_ , // Comma macro, to pass into args, comma not used directly
///
/// Indirection for methods having return values and arguments (other than
/// this). For methods returning void or having no arguments, make something
/// similar).
///
#define _Generate_Indirection_RetEArgs(ret, name, ThisType, thisArg, eargs) \
extern "C" ret name ( ThisType thisArg, eargs ) \
{ \
return thisArg -> name ( eargs ); \
} \
_Generate_Indirection_RetEArgs(int, execute, SomeContainer, x, int y);

how to use c and c++ together

There is a example I find:
in main.c
int main() {
cppsayhello("Hello from C to C++");
return 0;
}
in cppsayhello.cpp
#include<iostream>
#include"cppsayhello.h"
extern "C" void cppsayhello(char* str);
void cppsayhello(char *str) {
std::cout << str << std::endl;
}
It works! main.c includes nothing so how can main.c know of the existence of the function cppsayhello? Would somebody tell me how it works behind the scenes.
(I'm now working on an embeded system. The bottom-level is written in C, and I want to use c++ to construct top-level application. But It's hard to work with 2 language.)
The main.c is compiled by a C compiler that allows implicit function declaration. When C compiler finds a function that is not declare yet it assumes it is int function() which means function with any number of any parameters in C.
C99 and newer does not allow implicit declaration and the code would not compile with C99 compliant compiler.
It is a sign that your C compiler predates the 1999 standard, since later C compilers will reject that main() function.
Generally speaking, with older C compilers, your C code will link even when the usage of an implicitly declared function does not match the actual definition. The result is undefined behaviour (although, in practice, the code often still works - one possible manifestation of undefined behaviour is that the code works as expected with at least some compilers).
It works behind the scenes because C - unlike C++ - does not support function overloading. So any function named cppsayhello() will be given the same name (in the object file) by the compiler, so the linker can match things up. So you could define your cppsayhello() to have any return type, and any set of arguments, you desire - your code will still compile and link. However, the linker must only see one definition (it will complain about a multiply defined symbol if it encounters more than one definition of anything - for example, linking two object files that each contain a definition of some function).
Your code would avoid the undefined behaviour if the main() function had visibility of a proper declaration of the function.
void cppsayhello(const char *);
int main()
{
cppsayhello("Hello from C to C++");
return 0;
}
That will prevent the main() function compiling if it uses the function in any manner inconsistent with the declaration.
The whole thing is undefined behavior and works by luck.
A few things happen behind the scenes but your compiler should complain a lot.
in your main.c: in C a function the compiler does not know is implicitly expected to be of return type int without checking the parameters. (this applies to C older than C99. C99 or later will give you an error with this code)
in your cppsayhello.cpp: thanks to the extern "C" your C++ compiler creates an object file that contains a function with C calling conventions, without name mangeling.
the linker took both objects and finds in cppsayhello.obj a exportet symbol cppsayhello and in main.c a required symbol cppsayhello. so it links the two.
obviously they have different signatures but in your case the returned value is ignored and the parameters are compatible. But the actual runtime behavior may depend on architecture and compiler.
In Short: Your example is very bad code.

Why I need C++ linkage for a template?

Sometimes I try to follow the logic of some rules, sometimes the logic of why things are happening the way they do defeats any law that I know of.
Typically a template it's described as something that lives only during the compilation phase and it's exactly equivalent to hand-writing some function foo for any given type T .
So why this code doesn't compile ( I'm using C++11 with gcc and clang at the moment but I don't think it's that relevant in this case ) ?
#include <iostream>
#include <cstdint>
#include <cstdlib>
extern "C" {
template <typename T>
T foo(T t)
{
return t;
}
}
int main()
{
uint32_t a = 42;
std::cout << foo(a) << '\n';
return EXIT_SUCCESS;
}
And the thing that defeats all the logic is that the complain is about the linkage, and the implicit message is that this code doesn't generate a function, it generates something else that after compilation it's not suitable for a C style linkage.
What is the technical reason why this code doesn't compile ?
Let's look at this from a simple perspective. At the very least, using extern "C" will remove the C++ name mangling. So, we then have your template, and we'll instantiate it twice.
int foo(int val);
float foo(float val);
Under C's naming rules, these are required to have the same name foo from the perspective of the linker. If they have the same name though, we can't distinguish between them, and we'll have an error.
Under C++, the rules for how names are mangled is implementation defined. So C++ compilers will apply a name mangling to these two functions to differentiate them. Perhaps we'll call them foo_int and foo_float.
Because C++ can do this, we have no issues. But extern "C" requires the compiler to apply the C naming rules.
"linkage" is a slightly misleading term. The main thing that extern "C" changes is name mangling. That is, it produces symbol names in the object files that are compatible with the sort of symbols that equivalent C code would produce. That way it can link with C object code.... but it's a different sort of thing than specifying static or extern linkage.
But templates don't have a C equivalent, and name mangling is used to make sure that different instantiations of a given templated function result in different symbol names (so that the linker knows which one to use in a given place).
So there's no way to give templates C linkage; you're asking the compiler to do two fundamentally incompatible things.
Well other answers have explained why it doesn't work from the C++ side.
From the C side there are work-rounds but they are not portable.
You can simply not use the extern "C" keyword, create name-mangled functions and then in the C code link to the actual mangled names.
To make that easier you could also use GCC's abi::__cxa_demangle() function combined with a look-up table so you don't need to know what the mangled function names are (just their demangled signature).
But it all a bit of a bodge really.
Of course if you only call the template functions from C code, they'll never get instantiated to begin with. So you would need to make sure they get called in the C++ code to make sure they're present in the object file.

C/C++ definitions of functions

Yesterday, I have been watching discussion here, about compilers and linkers. It was about C library function definitions. I have never thought of that, so it inspired me to do some searching, but I cannot find exactly what I want. I wonder, what is the smallest syntax you need to add into your source code to enable just printf() function. I mean the function declaration from stdio.h you need.
The C99 declaration of printf() is
int printf(const char *restrict, ...);
but most compilers will also accept
int printf(const char *, ...);
See also C99 section 7.1.4, §2:
Provided that a library function can be declared without reference to any type defined in a
header, it is also permissible to declare the function and use it without including its
associated header.
Note: In this case, the restrict qualifier combined with const promises the compiler that the format string is never modified within printf(), even if the pointer is passed again as one of the variadic arguments.
The definition is usually compiled in a shared library. The declaration is what you need. Not having a declaration in scope invokes undefined behavior. So, for every library, you'd typically have a (set of) header file(s) and the compiled binary shared/static library. You compile your sources by including appropriate headers and link with the library. To bring in the declaration in scope use the #include directive. E.g. for printf you'd do:
#include <stdio.h>
int main() {
printf("Hello, world\n");
return 0;
}
But then any decent book on C or C++ should already cover this in detail and with better examples.
It depends on your compiler and platform.
On most cases just declaring
int printf(const char *, ...);
will just do, however, your particular compiler/platform or C library implementation even can change this declaration, for calling convention purposes.
All in all it is not worth it to try and declare things yourself, as this could be a violation of the one definition rule. You should always include the apropriate header, stdio.h(cstdio for C++) in this case.