I have a medium length C file with a bunch of functions (NOT under a header file - just a bunch of functions), that I wish to gather and use under a C++ project I'm developing.
Now I've read about the extern function but I've only seen it work on small C functions that are under a .h file.
But I wish to include these functions without messing with the C files themselves since I don't really understand them - I just need the function "under the hood". Is there any easy simple solution to this problem?
Yes, you just need some extern "C" declarations visible in your C++ code:
extern "C" {
int my_C_function_1(void);
int my_C_function_2(void);
}
This can either go in a suitable header, or if it's only used within one particular .cpp file then you could just put it there.
Note that if your C functions are already declared within a C header somewhere you can just do this within your .cpp file:
extern "C" {
#include "my_C_header.h"
}
You need to make a C++ header file myheader.hh. It starts with
#ifndef MYHEADER_INCLUDED
#define MYHEADER_INCLUDED
extern "C" {
then you declare all your public C functions, types, macros, etc.... At last you end it with
}; // end extern C
#endif MYHEADER_INCLUDED
In your C++ program, add #include "myheader.hh"
Alternatively (and instead of using myheader.hh), you might add (after other includes, but before C++ code) in your C++ file something like
extern "C") {
#include "your-C-code.c"
};
(But it might not work).
You'll need to declare the functions, typically in a header file, in order to call them from C++. If you compile these functions with a C compiler, then you will indeed need to surround the declarations with extern "C"; e.g.
extern "C" {
int foo(int, int);
}
If you have the source, then you could also modify it to include the header file (sans extern "C") and compile the functions with your C++ compiler.
Related
I saw a section of codes defined inside a .cpp file like this:
extern "C"
{
#include <user_interface.h>
#include <lwip/netif.h>
uint8 wifi_get_opmode(void)
{
return STATION_MODE;
}
bool wifi_station_get_config(struct station_config *config)
{
strcpy((char*)config->ssid, "emulated-ssid");
strcpy((char*)config->password, "emulated-ssid-password");
config->bssid_set = 0;
for (int i = 0; i < 6; i++)
config->bssid[i] = i;
return true;
}
}
My understanding of extern "C" keyword is to disable name mangling, so the functions defined inside a .c file and compiled with a c compiler can be linked and called from a cpp code. Which means, these C functions should be defined inside a .c file, then they will be compiled to a C-type object file by using a C compiler.
However, here the functions enclosed by extern "C" are defined (not declared) inside a .cpp file. What is the purpose of doing this?
The purpose would be to define the functions using "C" linkage. Meaning: don't mangle their names but compile them just like normal C++ functions would be, otherwise.
They can be called directly from C code that gets linked with this translation unit (subject to a suitable declaration), or from another C++ translation unit that declares these symbols as extern "C".
You're actually doing this all the time. When you put extern "C" in header files, the headers are also included in the implementation file for the functions they declare.
To correctly link a function, the function name must be identical in both the translation unit that defines them and the translation unit that includes them, so you have to use extern "C" in both (in the case they are both C++ of course).
I'm writing a C program (myapp) which needs to use a particular api; the api is written in C++. I've worked with C and C++, but never both at once, and I'm getting confused.
So, the api provides the following directory, which I've placed in a folder called include, at the same level as my makefile:
libmyapi.a
api/api.h
My main source file is src/myapp.c, and it includes the api using #include "api/api.h".
My make command is (plus some flags, which I haven't listed because I don't think they're relevant here):
gcc -Linclude -lmyapi -Iinclude src/myapp.c -o lib/myapp.sp -lrt
The problem I'm having is that the api.h file contains references to namespaces etc. Eg at one point it has:
namespace MyAPI {
namespace API {
typedef SimpleProxyServer SimpleConnection;
}
}
and obviously the C compiler doesn't know what this means.
So, I assumed I'd need to compile using a C++ compiler, but then someone said I didn't, and I could just "wrap" the code in "extern 'C'", but I don't really understand. Having read around online, I'm not any further on.
Do I need to compile in C++ (ie using g++)?
Do I need to "wrap" the code, and what does that mean? Do I just do
#ifdef __cplusplus
extern "C" {
namespace MyAPI {
namespace API {
typedef SimpleProxyServer SimpleConnection;
}
}
}
#endif
or do I just wrap the lines
namespace MyAPI {
namespace API {
and then their corresponding }}?
The header file calls other header files, so potentially I'll need to do this in quite a lot of places.
So far I've got errors and warnings with all the variations I've tried, but I don't know whether I'm doing the wrapping wrong, setting g++ compiler flags wrong, using the wrong compiler, or what! If I know the method to use, I can at least start debugging. Thank you!
You can write a small C++ program that creates a C binding for the API.
Gvien this API:
namespace MyAPI {
namespace API {
typedef SimpleProxyServer SimpleConnection;
}
}
you can create c_api.h
#ifdef __cplusplus
extern "C" {
#endif
struct api_handle_t;
typedef struct api_handle_t* api_handle;
api_handle myapi_api_create();
void myapi_api_some_function_using_api(api_handle h);
void myapi_api_destroy(api_handle h);
#ifdef __cplusplus
}
#endif
and c_api.cpp
#include "c_api.h"
#include <myapi/api/stuff.hpp>
struct api_handle_t
{
MyAPI::API::SimpleConnection c;
};
api_handle myapi_api_create()
{
return new api_handle_t;
}
void myapi_api_some_function_using_api(api_handle h)
{
//implement using h
}
void myapi_api_destroy(api_handle h)
{
delete h;
}
compile that with a C++ compiler and include the c_api.h file in the C project and link to the library you created with the C++ compiler and the original library.
Basically, your C++ library needs to export a pure C API. That is, it must provide an interface that relies solely on typedef, struct, enum, preprocessor directives/macros (and maybe a few things I forgot to mention, it must all be valid C code, though). Without such an interface, you cannot link C code with a C++ library.
The header of this pure C API needs to be compilable both with a C and a C++ compiler, however, when you compile it as C++, you must tell the C++ compiler that it is a C interface. That is why you need to wrap the entire API within
extern "C" {
//C API
}
when compiling as C++. However, that is not C code at all, so you must hide the extern "C" from the C compiler. This is done by adding the preprocessor directives
#ifdef __cplusplus1
extern "C" {
#endif
//C API
#ifdef __cplusplus1
}
#endif
If you cannot change your libraries header, you need to create a wrapper API that offers this pure C API and calls through to the respective C++ code.
How do I call C++ functions from C?
By writing calling functions whose declarations are valid in the common subset of C and C++. And by declaring the functions with C language linkage in C++.
The problem I'm having is that the api.h file contains references to namespaces
Such header is not written in common subset of C and C++, and therefore it cannot be used from C. You need to write a header which is valid C in order to use it in C.
Do I need to compile in C++ (ie using g++)?
If you have function definitions written in C++, then you need to compile those C++ functions with a C++ compiler. If you have C functions calling those C++ functions, then you need to compile those C functions with C compiler.
A minimal example:
// C++
#include <iostream>
extern "C" void function_in_cpp() {
std::cout << "Greetings from C++\n";
}
// C
void function_in_cpp(void);
void function_in_c(void) {
function_in_cpp();
}
You cannot. You can use C functions in your C++ program. But you cannot use C++ stuff from C. When C++ was invented, it allowed for compatibility and reuse of C functions, so it was written as a superset of C, allowing C++ to call all the C library functions.
But the reverse is not true. When C was invented, there was no C++ language defined.
The only way you can call C++ functions is to convert your whole project into a C++ one... you need to compile your C functions with a C++ compiler (or a C compiler if they are plain C) but for a C function to call a C++ function it must be compiled as C++. You should declare it with:
extern "C" {
void my_glue_func(type1 param1, type2 param2, ...)
{
/* ... */
}
} /* extern "C" */
and link the whole thing as a C++ program (calling the c++ linker)
This is because C doesn't know anything about function overloading, class initializacion, instance constructor calls, etc. So if you even can demangle the names of the C++ functions to be able to call them from C (you had better not to try this), they will probably run uninitialized, so your program may (most) probably crash.
If your main() function happens to be a C function, then there's no problem. C++ was designed with this thing in mind, and so, main() is declared implicitly as extern "C". :)
My C++ program needs to use an external C library.
Therefore, I'm using the
extern "C"
{
#include <library_header.h>
}
syntax for every module I need to use.
It worked fine until now.
A module is using the this name for some variables in one of its header file.
The C library itself is compiling fine because, from what I know, this has never been a keyword in C.
But despite my usage of the extern "C" syntax,
I'm getting errors from my C++ program when I include that header file.
If I rename every this in that C library header file with something like _this,
everything seems to work fine.
The question is:
Shouldn't the extern "C" syntax be enough for backward compatibility,
at least at syntax level, for an header file?
Is this an issue with the compiler?
Shouldn't the extern "C" syntax be enough for backward compatibility, at least at syntax level, for an header file? Is this an issue with the compiler?
No. Extern "C" is for linking - specifically the policy used for generated symbol names ("name mangling") and the calling convention (what assembly will be generated to call an API and stack parameter values) - not compilation.
The problem you have is not limited to the this keyword. In our current code base, we are porting some code to C++ and we have constructs like these:
struct Something {
char *value;
char class[20]; // <-- bad bad code!
};
This works fine in C code, but (like you) we are forced to rename to be able to compile as C++.
Strangely enough, many compilers don't forcibly disallow keyword redefinition through the preprocessor:
#include <iostream>
// temporary redefinition to compile code abusing the "this" keyword
#define cppThis this
#define this thisFunction
int this() {
return 1020;
}
int that() {
return this();
}
// put the C++ definition back so you can use it
#undef this
#define this cppThis
struct DumpThat {
int dump() {
std::cout << that();
}
DumpThat() {
this->dump();
}
};
int main ()
{
DumpThat dt;
}
So if you're up against a wall, that could let you compile a file written to C assumptions that you cannot change.
It will not--however--allow you to get a linker name of "this". There might be linkers that let you do some kind of remapping of names to help avoid collisions. A side-effect of that might be they allow you to say thisFunction -> this, and not have a problem with the right hand side of the mapping being a keyword.
In any case...the better answer if you can change it is...change it!
If extern "C" allowed you to use C++ keywords as symbols, the compiler would have to resolve them somehow outside of the extern "C" sections. For example:
extern "C" {
int * this; //global variable
typedef int class;
}
int MyClass::MyFunction() { return *this; } //what does this mean?
//MyClass could have a cast operator
class MyOtherClass; //forward declaration or a typedef'ed int?
Could you be more explicit about "using the this name for some variables in one of its header files"?
Is it really a variable or is it a parameter in a function prototype?
If it is the latter, you don't have a real problem because C (and C++) prototypes identify parameters by position (and type) and the names are optional. You could have a different version of the prototype, eg:
#ifdef __cplusplus
extern "C" {
void aFunc(int);
}
#else
void aFunc(int this);
#endif
Remember there is nothing magic about header files - they just provide code which is lexically included in at the point of #include - as if you copied and pasted them in.
So you can have your own copy of a library header which does tricks like the above, just becoming a maintenance issue to ensure you track what happens in the original header. If this was likely to become an issue, add a script as a build step which runs a diff against the original and ensures the only point of difference is your workaround code.
When using G++ (e.g. version 4.5 on Linux) can anyone explain what will/can happen if a user writes a header file for a mixed C/C++ system like this:
#ifdef __cplusplus
extern "C" {
int myCPPfunc(some_arg_list....); /* a C++ function */
}
#endif
but here myCPPfunc() is a normal C++ function with a class def inside - i.e. it was wrongly labeled as a C function.
What is the impact of this?
The main impact of this is that you cannot overload it, e.g. this is legal:
int myCPPfunc(int a);
int myCPPfunc(char a);
But this is not:
extern "C"
{
int myCPPfunc(int a);
int myCPPfunc(char a);
}
It is perfectly legitimate to have the implementation of an extern "C" function use arbitrary C++ features. What you can't do is have its interface be something you couldn't do in C, e.g. argument overloading, methods (virtual or otherwise), templates, etc.
Be aware that a lot of the "something you couldn't do in C" cases provoke undefined behavior rather than prompt compile errors.
This tells the C++ compiler that the functions declared in the header file are C functions.
http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.2
This is exactly what extern "C" is for - it allows you to write a C++ function that can be called from C.
Essentially, that declaration is telling the C++ compiler that you want the C++ function myCPPfunc() to have an external interface that is linkable (and therefore callable) from C.
The implementation of the function is still C++ and can still use C++ features.
Typically, the declaration of the function in the header file might look more like:
#ifdef __cplusplus
extern "C" {
#endif
int myCPPfunc(some_arg_list....); /* a C++ function */
#ifdef __cplusplus
}
#endif
That lets the same header file be used by either the C++ compiler or the C compiler, and each will see it as declaring a C callable function.
I want to use some c++ classes in shared library with C linkage. And i got following problems.
If
#include <iostream>
extern "C"
{
void f(){}
}
Compiles and links succesfully, but f() could not be found in resulting library.
If
extern "C"
{
#include <iostream>
void f(){}
}
I got many compiler errors (just dont know how to correctly translate them in english, something about template with C linkage) on every occurence of C++ keyword "template" in iostream and included headers.
What should be done?
The first variant is correct. Only stuff that even exists in C can be declared in a extern "C" block, and templates and classes certainly don't belong in that category. You only have to make sure, that your function is also declared as extern "C" in the header if you are using a C++-compiler. This is often achieved by writing
#ifdef __cplusplus
// C++ declarations (for example classes or functions that have C++ objects
// as parameters)
extern "C"
{
#endif
// C declarations (for example your function f)
#ifdef __cplusplus
}
#endif
in the header.
The first is correct; system headers (and most other headers as well)
can only be included at global scope, outside any namespaces, classes,
functions or linkage specification blocks. There are likely things in
<iostream> that wouldn't be legal in an extern "C", and even if
there weren't, the name mangling for extern "C" is almost certainly
different from that of C++, and the library itself was surely compiled
as extern "C++".
How did you define f? This could be a similar problem: if the source
file compiles it as an extern "C++" function, then the name will be
mangled differently than it was in the client files which compiled it as
an extern "C" function.
The general policy here is to handle the headers and the function
definitions/declarations in the same way you normally do, except that
you ensure that the header can be included in both C and C++ sources,
e.g.:
#if __cplusplus
extern "C" {
#endif
void f();
// Other `extern "C"` functions...
#if __cplusplus
}
#endif
Then include this header in all files where the function f() is used,
and in the file where it is defined.
Use __declspec to export functions, classes, etc...
Also: http://msdn.microsoft.com/en-us/library/a90k134d(v=vs.80).aspx
And this one is very good: http://www.flounder.com/ultimateheaderfile.htm