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.
Related
Lately, some of my CPP tutorials have used function prototypes . I understand you must initialize the function, but what is the overall use of it? Couldn't you use just as well write the entire function before main() instead of defining a prototype?
int returnValue(void);
int main()
{
std::cout << returnValue() << std::endl;
return 0;
}
int returnValue(void)
{
return 10;
}
Couldn't you use just as well write the entire function before main() instead of defining a prototype?
I can think of the following cases where you cannot.
Functions used in multiple files
If a function is used in multiple source (.cpp) files, you can define the function only in one source file. You have to declare it in the remaining source files. For convenience and to avoid errors, such declarations are put in header files. The header files are then #included by the source files.
Mutually recursive functions
If foo calls bar and bar calls foo, you cannot implement them without providing a declaration of at least one of the functions.
As a matter of good practice, it's better to declare both functions first. Then you can implement them in any order.
One important usage case is when you separate your implementation from the declarations. In other words, you declare your functions/classes etc in a header file, and define (i.e. implement) them in cpp files. In this way, you can distribute your program with the implementation fully compiled in a shared or static library. In order to use a pre-compiled function you need to introduce it to your program via a declaration. Example:
a.h
void f();
a.cpp
void f(){/* implementation here */}
main.cpp
#include "a.h"
int main()
{
f();
}
Including "a.h" in main() is declaring the function. Once you compile the a.cpp once, you don't need it's source any more, the program will run provided you have at least access to the object file, but in order for the linker to find the function f() you need to declare it.
If one doesn’t specify the function prototype, the behavior is specific to C standard (either C90 or C99) that the compilers implement. Up to C90 standard, C compilers assumed the return type of the omitted function prototype as int. And this assumption at compiler side may lead to unspecified program behavior.
Later C99 standard specified that compilers can no longer assume return type as int. Therefore, C99 became more restrict in type checking of function prototype. But to make C99 standard backward compatible, in practice, compilers throw the warning saying that the return type is assumed as int. But they go ahead with compilation. Thus, it becomes the responsibility of programmers to make sure that the assumed function prototype and the actual function type matches.
To avoid all this implementation specifics of C standards, it is best to have function prototype.
If you use extern C it with C++ files, does that allow defined C behavior that is undefined in C++?
blah.h
extern "C"
{
struct x {
int blah;
char buf[];
};
char * get_buf(struct x * base);
struct x * make_struct(int blah, int size);
}
some_random.cpp
#include "blah.h"
...
x * data=make_struct(7, 12);
std::strcpy(get_buf(data), "hello");
Is using the defined behavior in C's flexible array member, defined behavior when used this way?
Flexible array members are a standard feature of C, starting with the 1999 standard. They do not exist in C++.
Your code is not valid C++. Wrapping it in extern "C" doesn't change that. A conforming C++ compiler must at least warn about it, and arguably should reject it.
It happens that g++ implements C-style flexible array members as an extension to C++. That's perfectly legitimate (compilers are allowed to implement extensions), but its use is not portable. Its behavior, like that of any language extension, is defined by the compiler, not by the language.
If you compile it with g++ -pedantic, you'll get a warning:
c.cpp:5:21: warning: ISO C++ forbids zero-size array ‘buf’ [-Wpedantic]
char buf[];
^
If you want to use C-style flexible array members in a C++ program without relying on a compiler-specific extension, you can compile your C code as C and link it into your C++ program. You can't make the type with the flexible array member visible to your C++ code, but you can use it internally in the C code, and perhaps provide access to it in your C++ code via an opaque pointer. See the C++ FAQ for information about mixing C and C++ within the same program. (Or you can just use the g++ extension, at the cost of not being able to compile your code with other compilers.)
(I'm assuming that you're using g++. Some other compilers probably implement similar extensions.)
No.
extern "C" is only a linkage specification, so that enclosed symbols can be linked to from C. It does not switch your compiler to "C mode" for a section of code.
An extern "C" declaration only affects linkage of external functions, so that name mangling is not performed. It doesn't mean that the functions will be compiled using the rules of the C language instead of C++. In other words, including the code in some_random.cpp will not make its behavior defined.
It's just ascii until such time as the compiler runs. So the preprocessor will paste the files together, then the compiler will treat the result as whatever language you specified.
It isn't a C flexible array member, it's a text file. Undefined behaviour remains.
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.
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.
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.