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.
Related
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);
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.
I have .obj with function that has everything it needs to be linked as C++ member function. Problem is, it's in C and thus the class using it expects something uglier than it's normal name. So I figure this can be done in only 2 ways: either mangle the name of the C function and/or add additional symbol to the symbol table that would have the mangled name anyway, but I could still use it's original name too.. so mangle the name basically. Any ideas how to do this or have some completely other way of solving this? Please share but do consider usefulness of saying extern "C" in this particular case :)) thx
Your (C-based) object file has a symbol and you cannot redefine that symbol to have a different name -- that would be a task for the compiler generating that object file. The C compiler doesn't know about C++ and it cannot be made to emit a symbol with C++ linkage and name mangling. So the only way to use that symbol (your C function) is to call it by the symbol it is know for.
You can, of course, use that function to implement a C++ (member) function (the additional level of indirection is optimised away if the call is inline) as in
extern "C" { int my_C_func(void*, int); } // could be in an included header
struct A {
// implement the followind member using the C function
int operator()(int i) { return my_C_func(this,i); }
};
If the C++ class is already declared and its declaration cannot be touched, then you can still implement the member function in the same way in a separate source file. However, this cannot be inline and hence comes at the cost of an additional function call:
in file.cpp:
extern "C" { int my_C_func(void*, int); } // could be in an included header
int A::operator()(int i) { return my_C_func(this,i); }
From your reply to me comment, I conclude that you actually have control of the implementation of the C function. So, why do you need to implement this in C? Why can't you simply implement it in C++? Then you will get the correct linkage and name mangling and you can directly implement the desired member function.
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.
I want to implement a project in C, but it is comfortable to code some part of project in C++ and then call them from main C code.
Is it possible?! if yes, how I can do it?!
thanks in advance :)
P.S.
I used some libraries in my C++ Code such as OpenCV.
You'll need to "wrap" your C++ interface with regular C functions that take a parameter to indicate what object they'll be called on. For instance, if you have in C++
class A
{
// .. boilerplate stuff...
int SomeMethod(int n, float f);
};
Then along with it, you could declare a function such as
extern "C" int A_SomeMethod(void* Obj, int n, float f)
{
return(((A*)Obj)->SomeMethod(n, f));
}
If you're not comfortable with the casting of the void*, you can implement some kind of map from an opaque handle to an A*. But the gist is you'll need to keep around some handle/pointer to the object that the method will be called on. In order to get the pointer/handle you'll need to wrap the allocation to:
extern "C" void* A_Instantiate()
{
return new A;
}
The C++ files should be compiled separately along with the file with the functions above. A separate include for the C compilation should include declarations of all the functions above.
EDIT: The caveats and comments below are important; to answer the question, "Yes it is possible to call C++ from C", and this is one approach. It's not a complete approach as there isn't really a mechanistic way to do it, but it's a start. Also, don't forget to create another call-through for delete, etc, etc.
Q: Can I access my C code from C++ or vice versa?
A: Yes.
1) The main thing is to use extern "C" { ...} in all your headers to denote C-only functions and data, like this:
http://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B
/* Header file foo.h */
#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */
extern "C" {
#endif
/* These functions get C linkage */
void foo();
struct bar { /* ... */ };
#ifdef __cplusplus /* If this is a C++ compiler, end C linkage */
}
#endif
2) The usual scenario is a C++ main program that calls a mix of C and C++ functions and structs. The structs and functions are all declared in headers, and all have "#ifdef __cplusplus/extern C".
3) Here is a good FAQ on mixing C and C++:
http://www.parashift.com/c++-faq/mixing-c-and-cpp.html
Unless strictly required, this is only for dyied-in-the-wool masochists. Doing it will require extreme care on both sides, and could well work today and explode spectacularly with the next compiler update. C++ requires a lot of runtime help, and getting that to work reliably from C isn't normally supported. You can call into C from C++, that is officially supported (and part of the standard, extern "C" and such).
Probably the best bet is to write your C in the subset handled by C and C++ (a starting point on the subtle differences is this) and compile with the C++ compiler. Or get over it and decide what language you like most.
yes, you need to specify it as
extern "C"
this way it will make the function to have "C" linkage, then C code can call your function just as if it was in C. This function name will not be mangled then because C doesn't support overloading.
here let me cite #Faisal Vali:
extern "C" is a linkage-specification
Every compiler is required to provide "C" linkage
a linkage specification shall occur only in namespace scope
all function types, function names and variable names have a language linkage
two function types with distinct language linkages are distinct types even if otherwise identical
linkage specs nest, inner one determines the final linkage
extern "C" is ignored for class members
at most one function with a particular name can have "C" linkage (regardless of namespace)
extern "C" forces a function to have external linkage (cannot make it static)
Linkage from C++ to objects defined in other languages and to objects defined in C++ from other languages is implementation-defined and language-dependent. Only where the object layout strategies of two language implementations are similar enough can such linkage be achieved
see Faisal Vali answer here