proper usage of C dummy functions replacement in different environment - c++

I am trying to add test functions in a suite on both windows and linux machines. On linux machines i want the real functions to be added and on windows machine i want the dummy UnsupportedFunction to be added so that i can have same number of functions on both environments.
I have the following code
void UnsupportedFunction(struct1* test)
{
//dummy function in C
}
// following functions defined else where and gets added only if its linux box
#if ENV_LINUX
extern void linuxOnlyFunc1(struct1* test);
extern void linuxOnlyFunc2(struct1* test);
extern void linuxOnlyFunc3(struct1* test);
extern void linuxOnlyFunc4(struct1* test);
#endif
static struct1* addTest(params, TestFunction fnPtr) {
...
}
static void addTestToSuite (struct1* suite,
input devices,
TestFunction testFunction,
const char* testName,
const char* testDescription)
{
TestFunction fnPtr = UnsupportedFunction;
#if ENV_LINUX
fnPtr = linuxOnlyFunc1;
#endif
LinWB_Util_AddTest(params, fnPtr);
}
the issue is since i have lot of tests to be added to the suite, i have to make an ugly if-defines on all the entries. To get rid of these i have to abstract with a function call but, those externed functions doesnt exist on windows env and i end up getting compiler errors or warnings (considered errors).
how can one design this in a better way ?

How about something like
#if ENV_LINUX
extern void linuxOnlyFunc1(struct1* test);
extern void linuxOnlyFunc2(struct1* test);
extern void linuxOnlyFunc3(struct1* test);
extern void linuxOnlyFunc4(struct1* test);
#else
#define linuxOnlyFunc1 UnsupportedFunction
#define linuxOnlyFunc2 UnsupportedFunction
...
#endif

I haven't tested this, so it might need some tweaking, but you could do something like this:
#if ENV_LINUX
#define linux_only(x) extern void x(struct1* test);
#else
#define linux_only(x) inline void x(struct1* test) { UnsupportedFunction(test); }
#endif
linux_only(linuxOnlyFunc1);
linux_only(linuxOnlyFunc2);
linux_only(linuxOnlyFunc3);
linux_only(linuxOnlyFunc4);

You could use include files to store your function declarations. Thus you dont't have to write them into every source file. And if the functions turn out to be undefined, just write such functions.
upon request, I elaborate.
You create a file called "fakefuns.h" which contains your function declarations:
#if ENV_LINUX
extern void linuxOnlyFunc1(struct1* test);
extern void linuxOnlyFunc2(struct1* test);
extern void linuxOnlyFunc3(struct1* test);
extern void linuxOnlyFunc4(struct1* test);
#endif
Then you can include these definition in every source file by adding
#include "fakefuns.h"
into the source file, preferably near to the first line. And in one source file, you actually implement these functions, both for Linux and Windows. And if they should not to any work in Windows, the implementations will be very simple.

Related

Calling a function from a DLL which is developed in C++ from C

The function in dll has the prototype below
void Foo(int arg1, int& arg2);
The question is, how to declare the function prototype in C?
Is the declaration legal?
void Foo(int, int*);
Is the declaration legal?
It is, but it doesn't declare the same function. If you need a C API, you cannot use a reference. Stick to a pointer, and make sure the function has C linkage:
extern "C" void Foo(int, int*) {
// Function body
}
If you cannot modify the DLL code, you need to write a C++ wrapper for it that exposes a proper C API.
You need an adapter, consisting of a C++ translation unit and a header usable from both C and C++, like this (use better names of course):
adapter.h:
#ifndef ADAPTER_H
#define ADAPTER_H
#endif
#ifdef __cplusplus
extern "C" {
#endif
void adapter_Foo(int arg1, int *arg2);
// more wrapped functions
#ifdef __cplusplus
}
#endif
#endif
adapter.cpp:
#include "adapter.h"
// includes for your C++ library here
void adapter_Foo(int arg1, int *arg2)
{
// call your C++ function, e.g.
Foo(arg1, *arg2);
}
You can compile this adapter into a separate DLL or you can have it as a part of your main program. In your C code, just #include "adapter.h" and call adapter_Foo() instead of Foo().

Call a C++ function from Swift

How should I call a C++ function (no classes involved) from a Swift file?
I tried this:
In someCFunction.c:
void someCFunction() {
printf("Inside the C function\n");
}
void aWrapper() {
someCplusplusFunction();
}
In someCpluplusfunction.cpp:
void someCplusplusFunction() {
printf("Inside the C++ function");
}
In main.swift:
someCFunction();
aWrapper();
In Bridging-Header.h:
#import "someCFunction.h"
#import "someCplusplusFunction.h"
I found this answer very informative, but still I cannot make it work.
Could you point me in the right direction?
Thanks!
What does the header look like?
If you want to explicitly set the linking type for C-compatible functions in C++, you need to tell the C++ compiler so:
// cHeader.h
extern "C" {
void someCplusplusFunction();
void someCFunction();
void aWrapper();
}
Note that this isn't valid C code, so you'd need to wrap the extern "C" declarations in preprocessor macros.
On OS X and iOS, you can use __BEGIN_DECLS and __END_DECLS around code you want linked as C code when compiling C++ sources, and you don't need to worry about using other preprocessor trickery for it to be valid C code.
As such, it would look like:
// cHeader.h
__BEGIN_DECLS
void someCplusplusFunction();
void someCFunction();
void aWrapper();
__END_DECLS
EDIT: As ephemer mentioned, you can use the following preprocessor macros:
// cHeader.h
#ifdef __cplusplus
extern "C" {
#endif
void someCplusplusFunction();
void someCFunction();
void aWrapper();
#ifdef __cplusplus
}
#endif

GCC: linker error when working with old C code

I'm running into a mysterious situation with the GCC compiler. So I've got the following files:
//main.cpp
#include "mleak_cpp.h"
int main(int argc, char* argv[])
{
foo();
__memory_malloc(10,"hello",5);
return 0;
}
//mleak_cpp.h
......
void foo(void);
void* __memory_malloc(size_t size, const char* file, int line);
//mleak_cpp.cpp
//definitions of the functions;
void foo(void){printf("foo\n");
void* __memory_malloc(size_t size, const char* file, int line){
printf("%s,%d\n",file,line);
InitDoubleLinkList();
void* p = malloc(size);
if(p == NULL)
return NULL;
__DuLinkList* pListNode;
pListNode = (__DuLinkList*)malloc(sizeof(__DuLinkList));
pListNode->address = p;
pListNode->memorysize = size;
pListNode->file = file;
pListNode->line = line;
InsertBlockToList(pListNode);
return p;
}
For some reason, the call to void foo(void) is fine, but the call to "__memory_malloc" goes down with a linker error, "undefined reference" blah blah. What's the difference between the two functions that causes the different behaviour?
I tried adding "extern C" to the "#include" directive, so main.cpp reads:
extern "C"{
#include "mleak_cpp.h"
}
and adding the keyword "extern" before the declarations of the functions, and this time the call to "foo()" fails too with the same error.
I appreciate any help from you guys
You're placing extern "C" in the wrong place.
If main.c is truly a C file, and mleak_cpp.cpp is truly a C++ function, then you need to put an extern "C" ahead of the definition of __memory_malloc() like so:
extern "C" void* __memory_malloc(size_t size, const char* file, int line){
// ...
}
If you put extern "C" in the mleak_cpp.h file, it needs to be guarded:
#ifdef __cplusplus
extern "C" {
#endif
/* ... body of header ... */
#ifdef __cplusplus
}
#endif
Also, it's not clear why foo works in your example above, when one file calls __foo() but the other file defines foo(). I assume something more is at play, such as an editing error in your question.
extern "C" is for C++, not C, and tells it that the function's name shouldn't be mangled. In C code, you should never see this. Generally, you put it in header files, and you guard it, like this:
#ifdef __cplusplus
extern "C" {
#endif
/* C and C++ compatible header file body here */
#ifdef __cplusplus
} /* end extern "C" */
#endif
If you do it this way though, you need to include the header file in both your C and C++ files, so that the C++ compiler knows to use C linkage.
You can put the extern "C" in front of the function definition in C++ instead and leave it out of the header, but this only works if you only include the headers in C code, so it's recommended to do it the way I pointed out above.

Using a mixed C/C++ header to use C++ object in C

I have been following this guide on how to call a member function of a C++ object from C. As I've understood it, the C code should interpret the class as a struct of the same name, and whenever it wants to call a function through an object of this class it should use an intermediate callback function. The header looks like this:
// CInterface.h
#ifdef __cplusplus
...
class CInterface
{
public:
...
void OnMessage(U8* bytes); // I want to call this function from C.
private:
...
};
#else
typedef
struct CInterface
CInterface;
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__STDC__) || defined(__cplusplus)
//extern void c_function(CInterface*); /* ANSI C prototypes (shouldn't be needed) */
extern CInterface* cpp_callback_function(CInterface* self, unsigned char * bytes);
#else
//extern void c_function(); /* K&R style (shouldn't be needed) */
extern CInterface* cpp_callback_function(unsigned char * bytes);
#endif
#ifdef __cplusplus
}
#endif
The C code that fails right now looks like this:
// main.c
#include "CInterface.h"
int main(int argc, char* argv[])
{
void* ptr;
int *i = ptr; // Code that only compiles with a C compiler
CInterface cinterface; // This should declare a struct
}
The error is: error C2079: 'cinterface' uses undefined struct 'CInterface'.
It sounds like the header is being read as c++ code as the struct is not defined, but main.c is being compiled by C according to Visual Studio (I also double checked this by adding some C-specific code). However, if I add parentheses like this:
CInterface cinterface();
the code compiles which makes no sense to me as it now is an object which shouldn't work in C.
The callback function is implemented in a third file, CInterface.cpp, which acts as the "intermediate".
So the question is how I solve this error message, or if I got the entire approach wrong. It's the first time I mix C/C++ code and I'm relatively new to both languages.
In your example CInterface is only defined for C++. If you take a closer look at the example you linked you'll notice that this is also the case for the Fred class.
From C you can only pass around pointers to CInterface and you have to rely on C++ functions defined with C linkage to actually manipulate CInterface instances.
Otherwise you could define a struct as a means to pass around data between C and C++. Just ensure its definition is declared as extern "C" when used from C++:
#ifdef __cplusplus
extern "C" {
#endif
struct CandCPlusPlus {
// ...
};
#ifdef __cplusplus
}
#endif

How to call a c++ class and its method from a c file

I am trying to access a C++ class and call its method from a .c file.
I google this topic and find this http://developers.sun.com/solaris/articles/mixing.html
It says:
You can write extern "C" functions in C++ that access class M objects and call them from C code.
Here is a C++ function designed to call the member function foo:
extern "C" int call_M_foo(M* m, int i) { return m->foo(i); }
My question is where do I put the about line? In my C++ .h file? Or C .h file?
And it goes on and says:
Here is an example of C code that uses class M:
struct M; // you can supply only an incomplete declaration
int call_M_foo(struct M*, int); // declare the wrapper function
int f(struct M* p, int j) // now you can call M::foo
{
return call_M_foo(p, j);
}
But how/where do I create the class M in my C file?
And where do I put the above code? C .h file? C++ .h file? Or C .c file?
Thank you.
Thank you for GMan's detailed answer.
I did follow your suggestion. But I get compile error in my .c file.
main.c:33:
./some_class.h:24: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘attribute’ before ‘’ token
./some_class.h:25: error: expected ‘)’ before ‘’ token
./some_class.h:26: error: expected ‘)’ before ‘*’ token
And here are my some_class.h line 24-26:
#ifdef __cplusplus
class M {
public:
M();
virtual ~M();
void method1(char* name, char* msg);
};
extern "C" {
#else
struct M;
#endif
/* access functions line 24-26 are here*/
M* M_new(void);
void M_delete(M*);
void M_method1(M*, char*, char*);
#ifdef __cplusplus
}
#endif
For some reason, my C compiler does not like extern "C" in GMan's original some_test.h. So I have to modify to above. It seems like the C compiler does not like/understand the struct M; line.
Any idea will be much appreciated.
Your header file, which is shared between your C and C++ code:
#ifdef __cplusplus // only actually define the class if this is C++
class some_class
{
public:
int some_method(float);
};
#else
// C doesn't know about classes, just say it's a struct
typedef struct some_class some_class;
#endif
// access functions
#ifdef __cplusplus
#define EXPORT_C extern "C"
#else
#define EXPORT_C
#endif
EXPORT_C some_class* some_class_new(void);
EXPORT_C void some_class_delete(some_class*);
EXPORT_C int some_class_some_method(some_class*, float);
Then your source file:
#include "some_foo.h"
int some_class::some_method(float f)
{
return static_cast<int>(f);
}
// access functions
EXPORT_C some_class* some_class_new(void)
{
return new some_class();
}
EXPORT_C void some_class_delete(some_class* this)
{
delete this;
}
EXPORT_C int some_class_some_method(some_class* this, float f)
{
return this->some_method(f);
}
Now compile that source, and link to it. Your C source would be something like:
#include "some_class.h"
some_class* myInstance = some_class_new();
int i = some_class_some_method(myInstance, 10.0f);
some_class_delete(myInstance);
If you're serious about mixing C and C++, you'll want macro's.
Here are some sample macro's that would make this much easier:
// in something like c_export.h
// extern "C" macro
#ifdef __cplusplus
#define EXPORT_C extern "C"
#else
#define EXPORT_C
#endif
// new
#define EXPORT_C_CLASS_NEW(classname) EXPORT_C \
classname * classname##_new(void)
#define EXPORT_C_CLASS_NEW_DEFINE(classname) \
EXPORT_C_CLASS_NEW(classname) \
{ return new classname (); }
// repeat as much as you want. allows passing parameters to the constructor
#define EXPORT_C_CLASS_NEW_1(classname, param1) EXPORT_C \
classname * classname##_new( param1 p1)
#define EXPORT_C_CLASS_NEW_1_DEFINE(classname, param1) \
EXPORT_C_CLASS_NEW_1(classname, param1) \
{ return new classname (p1); }
// delete
#define EXPORT_C_CLASS_DELETE(classname) EXPORT_C \
void classname##_delete( classname * this)
#define EXPORT_C_CLASS_DELETE_DEFINE(classname) \
EXPORT_C_CLASS_DELETE(classname) \
{ delete this; }
// functions
#define EXPORT_C_CLASS_METHOD(classname, methodname, ret) EXPORT_C \
ret classname##_##methodname##( classname * this)
#define EXPORT_C_CLASS_METHOD_DEFINE(classname, methodname, ret) \
EXPORT_C_CLASS_METHOD(classname, methodname, ret) \
{ return this->##methodname##(); }
// and repeat as necessary.
#define EXPORT_C_CLASS_METHOD_1(classname, methodname, ret, param1) EXPORT_C \
ret classname##_##methodname( classname * this, param1 p1)
#define EXPORT_C_CLASS_METHOD_1_DEFINE(classname, methodname, ret, param1) \
EXPORT_C_CLASS_METHOD_1(classname, methodname, ret, param1) \
{ return this->##methodname##(p1); }
And so on. Our header/source becomes:
// header
#include "c_export.h" // utility macros
#ifdef __cplusplus // only actually define the class if this is C++
class some_class
{
public:
int some_method(float);
};
#else
// C doesn't know about classes, just say it's a struct
typedef struct some_class some_class;
#endif
// access functions
EXPORT_C_CLASS_NEW(some_class);
EXPORT_C_CLASS_DELETE(some_class);
EXPORT_C_CLASS_METHOD_1(some_class, some_method, int, float);
// source
#include "some_foo.h"
int some_class::some_method(float f)
{
return static_cast<int>(f);
}
// access functions
EXPORT_C_CLASS_NEW_DEFINE(some_class);
EXPORT_C_CLASS_DELETE_DEFINE(some_class);
EXPORT_C_CLASS_METHOD_1_DEFINE(some_class, some_method, int, float);
And that's much more concise. It could be made simpler (possibly) with variadic macro's, but that's non-standard and I leave that to you. :] Also, you can make macro's for normal non-member functions.
Note that C does not know what references are. If you want to bind to a reference, your best bet is probably just to write the export definition manually. (But I'll think about it, maybe we can get it automatically).
Imagine our some_class took the float by (non-const)reference (for whatever reason). We'd define the function like so:
// header
// pass by pointer! v
EXPORT_C_CLASS_METHOD_1(some_class, some_method, int, float*) ;
// source
EXPORT_C_CLASS_METHOD_1(some_class, some_method, int, float*)
{
// dereference pointer; now can be used as reference
return this->some_method(*p1);
}
And there we go. C would interface with references with pointers instead:
// c source, if some_method took a reference:
float f = 10.0f;
int i = some_class_some_method(myInstance, &f);
And we pass f "by reference".
You need to split it among the C++ header and implementation files.
foo.h:
extern "C" int call_M_foo(M* m, int i);
foo.cc:
extern "C" int call_M_foo(M* m, int i) {
return m->foo(i);
}
To create the object of type M, you would need a similar function:
foo.h:
struct M;
extern "C" M* create_M();
foo.cc:
extern "C" M* create_M() {
return new M;
}
You have several questions combined here so I will answer them individually.
My question is where do I put the about line? In my c++ .h file? or c .h file?
The extern "C" line goes in the C++ file. It essentially tells the compiler to
limit everything whithin the extern "C" block to the C subset of C++, and to
export functions declared in this area accordingly.
But how/where do I create the class M in my c file?
You can't. C does not have the concept of classes, and there's absolutely no
way to instantiate a class directly. You essentially have to export a C function
in your C++ file which creates the class and returns it as a pointer. Then you
can pass that pointer around your C application. You can't actually modify the
class directly in your C application, because C does not support classes, and
your C++ compiler may insert "hidden" variables for bookkeeping inside the
actual declaration of the class.
And where do I put the above code?
The piece of code that uses a structure pointer goes in the C file. You are
forced to use a structure pointer because C does not support classes at all.
You can put function calls using that function anywhere in a C implementation
file, just like normal C function calls.
All the information you need is in the link you provide. You just need to understand that there needs to be a strict separation between C and C++ code.
C++ code can call any C code.
C code usually cannot call any C++ code.
C functions can be implemented by C++ code.
The key part to understand is that the C and C++ compilers mangle function names when making object files in different ways, so they would normally not be able to interoperate (at link time), except that C++ can be prompted to know the difference by using extern "C"
The prototype:
void f(int); might be mangled by a C compiler to: _f, but a C++ compiler might choose a very different name eg f_int, and so the linker would not know they are supposed to be the same.
However:
extern "C" void f(int);
would be mangled by a C++ compiler to _f, but a C compiler would choke on the extern "C". To avoid this you should used something like this:
#ifdef __cplusplus
extern "C" {
#endif
void f(int);
#ifdef __cplusplus
} /* closing brace for extern "C" */
#endif
Now the whole of the above section can live in a .h file and is, as the sun.com article states, a mixed-language header.
This means that a .c or .cpp file can #include this header and code can call f();
and either a .c or .cpp file can #include this header and implement it:
void f()
{
}
Now the good bit is that a .cpp file can implement this to call any C++ code it likes.
Now to answer your specific questions:
The first code sample can only go in a .cpp file.
The second code sample can only go in a .c file.
Additionally class M must be declared and defined in C++ files only.
The site you have linked to has the answer already:
You can declare function print in a
header file that is shared by C and
C++ code:
#ifdef __cplusplus extern "C"
#endif int print(int i, double d);
You can declare at most one function
of an overloaded set as extern "C"
Here is the example C header for the
wrapper functions:
int g_int(int);
double g_double(double);
Basically, there can be a header shared between the two that declares the function prototype, adding the extern "C" modifier if you are in C++ to ensure the function can be accessed in an object from C. You define the body of the function later on in the C++ code as usual, if necessary inside a class etc, and you use the function in C like normal.