The following is some background as to what I want to do and why. The actual question is at the very bottom...
I have an API that has some format.
For instance
int f(void *str1, void *str2) {...}
I want to reimplement the system behind the API so that it can be a drop in replacement for the old system. However it turns out that str1 is now unnecessary and moreover doesn't make sense to have if you're aware that you're using my new system. Therefore, I want to be able to expose the underlying API that makes sense:
int f_internal(void *str2);
Right now I have code that looks like this:
#ifdef USE_INTERNAL
#define INTERNAL(sym) sym##_internal
#else
#define INTERNAL(sym) sym
#endif
extern "C" {
#ifndef USE_INTERNAL
int f(void *str1, void *str2){
return INTERNAL(f)(str2);
}
#endif
SOME_ATTRIBUTES
int
INTERNAL(f)(void *str2){
... // actual content
} EXPORT_FUNCTION_MACRO(INTERNAL(f), 1);
}
The effect is if I define USE_INTERNAL, a call to f(a) works, but I don't define it then we have to use the f(a, b).
The problem I am encountering is that EXPORT_FUNCTION_MACRO itself defines another function name but doesn't evaluate INTERNAL(F) first. This results in the message
dir: error: pasting ")" and "_" does not give a valid preprocessing token
INTERNAL(sym) \
--- NOTE--- EXPORT_FUNCTION_MACRO takes args 'sys' and 'n'
other_dir: note: in definition of macro ‘EXPORT_FUNCTION_MACRO’
void _example##sym##_##n(void) {} \
WHAT I WANT TO DO:
I want to have a compile flag that can change the number of arguments needed to call something.
Maybe something like (if it existed)
using f(a, b) = f_internal(a);
Any ideas?
This results in the message
To fix the message let macro arguments expand before concatenating them.
#define EXPORT_FUNCTION_MACRO_X(sys, n) EXPORT_FUNCTION_MACRO(sys, n)
EXPORT_FUNCTION_MACRO_X(INTERNAL(f), 1);
You could achieve that with a macro in the C part:
#define f(...) CONCAT(f, NUM(__VA_ARGS__, 2, 1)) (__VA_ARGS__)
#define CONCAT(X, Y) CC(X, Y)
#define CC(X, Y) X ## Y
#define NUM(X, Y, N, ...) N
#ifdef __cplusplus
extern "C"
#endif
void f_internal(void* str);
// specifically compiled for C or C++ anyway (and most likely inlined)
// -> no need for extern "C" for these:
void f1(void* str) { f_internal(str); }
void f2(void* unused, void* str) { f_internal(str); }
The macro f would select the correct function out of f1 and f2, which again would call f_internal with the correct argument. Works for both C and C++. If you prefer, you could still just provide two overloads for C++ separately and let only the C people deal with the macros.
I doubt one could call that 'elegant'; if you want to qualify as 'ugly' – up to you. But at least it works...
The following code behaves like this:
If USE_INTERNAL is defined, defines an inline (c++) / static (c) function int f(void* str).
Otherwise, defines an inline (c++) / static (c) function int f(void* str1, void* str2).
Both functions are trampolines to the actual (int f_internal(void* str)) function.
Note that since the functions are defined in the header, inline (c++) / static (c) is required to keep them from violating the ODR rule (I am a c++ person, so I don't know any way better than static to achieve this in c. If there is, please let me know).
#ifdef __cplusplus
extern "C"
#endif
int f_internal(void* str);
#ifdef USE_INTERNAL
#ifdef __cplusplus
inline
#else
static
#endif
int f(void* str1, void* str2) {
return f_internal(str2);
}
#else
#ifdef __cplusplus
inline
#else
static
#endif
int f(void* str) {
return f_internal(str);
}
#endif
Related
I'm trying to implement logging which produce no overhead when not needed (i.e. no method call should be performed at all). I want NO overhead because it's low-latency code. I just added #define ENABLE_LOGS to my header class and now it looks like that (you can ignore details)
#pragma once
#include <string>
#include <fstream>
#define ENABLE_LOGS
namespace fastNative {
class Logger
{
public:
Logger(std::string name_, std::string fileName, bool append = false);
~Logger(void);
void Error(std::string message, ...);
void Debug(std::string message, ...);
void DebugConsole(std::string message, ...);
void Flush();
static Logger errorsLogger;
static Logger infoLogger;
private:
FILE* logFile;
bool debugEnabled;
};
}
Every time I need to use some method I should surround it like that:
#ifdef ENABLE_LOGS
logger.Debug("seq=%6d len=%4d", seq, length_);
#endif
It's error-phrone (i can forgot to surround) and makes code dirty. Can I fix my code somehow not to use #ifdef every time?
In C# I like Conditional I guess I need something like that for c++.
First of all it would make sense to have a look to see what's out there already. This is a common problem and many people will have solved it before. E.g., see stackoverflow question C++ logging framework suggestions, and Dr Dobbs A Highly Configurable Logging Framework In C++.
If you do roll your own, you should get some good ideas from having done this. There are several approaches I've used in the past. One is to make the statement itself conditionally defined
#ifdef ENABLE_LOGS
#define LOG(a,b,c) logger.Debug(a, b, c)
#else
#define LOG(a,b,c)
#endif
Another approach is to conditionally define the logging class itself. The non-logging version has everything as empty statements, and you rely on the compiler optimizing everything out.
#ifdef ENABLE_LOGS
class Logger
{
public:
Logger(std::string name_, std::string fileName, bool append = false);
~Logger(void);
void Error(std::string message, ...);
void Debug(std::string message, ...);
void DebugConsole(std::string message, ...);
void Flush();
static Logger errorsLogger;
static Logger infoLogger;
private:
FILE* logFile;
bool debugEnabled;
};
#else
class Logger
{
public:
Logger(std::string name_, std::string fileName, bool append = false) {}
~Logger(void) {}
void Error(std::string message, ...) {}
void Debug(std::string message, ...) {}
void DebugConsole(std::string message, ...) {}
void Flush() {}
};
#endif
You could put your Logger implementation for ENABLE_LOGS in a cpp file under control of the macro. One issue with this approach is that you would want to be sure to define the interface so the compiler could optimize everything out. So, e.g., use a C-string parameter type (const char*). In any case const std::string& is preferable to std::string (the latter ensures there's a string copy every time there's a call).
Finally if you go for the first approach, you should encapsulate everything in do() { ... } while(0) in order to ensure that you don't get bizarre behavior when you use your macro where a compound statement might be expected.
There is one way (the way llvm does) to do this using macros.
#ifdef ENABLE_LOGS
#define DEBUG(ARG) do { ARG; } while(0)
#else
#define DEBUG(ARG)
#endif
Then use it as:
DEBUG(logger.Debug("seq=%6d len=%4d", seq, length_););
What I often see, is to use the #define to actually define the log calls, eg:
#define LOG_DEBUG(msg) logger.Debug(msg);
But you want to wrap the defines in a block that enables or disables your logging:
#ifdef ENABLE_LOGS
#define LOG_DEBUG(msg) logger.Debug(msg);
#else
#define LOG_DEBUG(msg)
#endif
You can call LOG_DEBUG anywhere in your code. If the logging is disabled, calling LOG_DEBUG ends up as a blank line in your final code.
A nice old trick is:
#ifdef ENABLE_LOGS
#define LOG Logger.Debug
#else
#define LOG (void)sizeof
#endif
Then the code:
LOG("seq=%6d len=%4d", seq, length_);
will expand to:
Logger.Debug("seq=%6d len=%4d", seq, length_);
that does the log. Or:
(void)sizeof("seq=%6d len=%4d", seq, length_);
that does absolutely nothing. It doesn't even evaluate the function arguments!!!
The trick is that the first version uses the comma as argument separator in a function call. In the second version, however, it is a unevaluated comma operator.
However, some compilers may give spurious warnings about unreachable code.
You could put the #ifdef inside the body of the individual functions. This avoid the code duplication issue in TooTone's answer.
Example:
void fastNative::Logger::Debug(std::string message, ...)
{
#ifdef ENABLE_LOGS
// do the actual logging
#endif
}
If ENABLE_LOGS isn't defined, this function doesn't do anything. What I would suggest is you pass a const char* instead of std::string to these method. That way, if ENABLE_LOGS is not defined, you wouldn't have to rely on the compiler to not create redundant std::string objects.
I want an inline way of specifying which prototypes should be included with c++. For example:
void ArrayList_insert(ArrayList *arrlst, void *data, int i);
IS_CPP void ArrayList_insert(ArrayList *arrlst, char *data, int i);
IS_CPP void ArrayList_insert(ArrayList *arrlst, Buffer *data, int i);
currently I am doing:
#ifdef __cplusplus
extern "C" {
#endif
....C HEADERS..
#ifdef __cplusplus
}
....C++ HEADERS...
#endif
but its very inconvenient because overloads of the same function are in different places. I could just have 2 different header files, but that is a pain too. Therefore, Im looking for an inline solution like i proposed above. Does anyone know of a way to do that?
It's easier than you think.
#ifdef __cplusplus
#define IS_C(x) extern "C" x ;
#define IS_CPP(x) x ;
#else
#define IS_C(x) x ;
#define IS_CPP(x)
#endif
With this type of header:
IS_C (void ArrayList_insert(ArrayList *arrlst, void *data, int i))
IS_CPP (void ArrayList_insert(ArrayList *arrlst, char *data, int i))
IS_CPP (void ArrayList_insert(ArrayList *arrlst, Buffer *data, int i))
Sure, you can do it almost like your example by using a function-like macro:
#ifdef __cplusplus
#define IS_CPP(x) x
#else
#define IS_CPP(x)
#endif
void ArrayList_insert(ArrayList *arrlst, void *data, int i);
IS_CPP(void ArrayList_insert(ArrayList *arrlst, char *data, int i));
IS_CPP(void ArrayList_insert(ArrayList *arrlst, Buffer *data, int i));
Now if you compile the header as C++, you'll get all three, but if you compile as C, you'll only get the one. If you want to share a single library between the two, you'll need to add some extern "C" qualifiers to the C function when compiling for C++. #MarkLakata's answer shows one possible way.
The usual approach is to just write it in the most obvious way:
void ArrayList_insert(ArrayList *arrlst, void *data, int i);
#ifdef __cplusplus
void ArrayList_insert(ArrayList *arrlst, char *data, int i);
void ArrayList_insert(ArrayList *arrlst, Buffer *data, int i);
#endif /* __cplusplus */
As #chacham15 points out, you also need, in a project-wide header,
#ifdef __cplusplus
#define EXTERN_C extern "C"
#endif /* __cplusplus */
and you need to decorate the C-callable function with EXTERN_C.
You can obviously abuse the preprocessor to hack together what you're asking, but why do it? Personally I would rather type mylst.insert(foop, 1); instead of ArrayList_insert(mylst, foop, 1); if I was using C++. In other words, I see little benefit in using the C style for calling the overloaded functions, but mixing the styles of the function calls that you as the code author created isn't exactly pretty either.
I'd make an ArrayList class that has the same members as in the C structure, and anytime you need to interface your class with the C functions, create a shallow copy if possible and pass that to the C function, then copy the information from that structure back into your class.
An alternative would be to wrap the structure in a C++ class and use that for the C interface functions.
Otherwise, you might try making the class inherit the C structure, assuming the structure's tag isn't named ArrayList and the typedef for the structure isn't visible from the C++ interface. Then you can hopefully pass the this pointer directly from within the member function as if it was the actual C structure. I'm not sure this method is portable in all cases, so I'd implement the former idea if possible, even if it does require copying data back and forth.
All ideas avoid code duplication, and the C++ interface looks more like C++ code instead of the bad mixture of C functions and C++ function overloading. Additionally, the interfaces are kept separate somewhat. No additional header files are necessary either as the C functions can be wrapped in an extern "C" block as usual:
#ifdef __cplusplus
extern "C" {
#endif
struct array_list_tag {
...
};
/* C functions here */
#ifdef __cplusplus
} /* extern "C" */
class ArrayList ...
#else /* !__cplusplus */
typedef struct array_list_tag ArrayList;
#endif
If you really want to get rid of the boilerplate and you are willing to use the preprocessor to do it, then just go ahead and write up the pattern. The general pattern you have looks like
extern "C" {
void C_accessible_declaration(); // this is all C sees
}
void Cxx_accessible_declaration_1( int );
void Cxx_accessible_declaration_1( long );
So you could make a macro,
#ifdef __cplusplus
# define C_PORTABLE_FUNCTION_SET( C_DECLS, CXX_DECLS ) \
extern "C" { C_DECLS } \
CXX_DECLS
#else
# define C_PORTABLE_FUNCTION_SET( C_DECLS, CXX_DECLS ) \
C_DECLS
#endif
This works because an ordinary function declaration cannot contain a comma not enclosed by parentheses. If you want it to work with templates (with comma-separated template parameters), then you can variadic macros, supported in C99, C++11, and various compilers preceding those standards as an extension.
#ifdef __cplusplus
# define C_PORTABLE_FUNCTION_SET( C_DECLS, ... ) \
extern "C" { C_DECLS } \
__VA_ARGS__
#else
# define C_PORTABLE_FUNCTION_SET( C_DECLS, ... ) \
C_DECLS
#endif
Now this works as long as the C declarations do not contain a naked comma, which means you shouldn't declare multiple objects in the one declaration. I've called it C_PORTABLE_FUNCTION_SET to emphasize it's mainly safe for use with function declarations, but note that you need to declare C-accessible objects within extern C as well. Shared struct definitions should not be protected at all; they are protected by the C++ POD concept, and do not carry language linkage.
Usage:
#ifdef __cplusplus
template< typename T, typename U >
class Buffer { // still use #ifdef for the general case
...
};
#endif
C_PORTABLE_FUNCTION_SET (
void ArrayList_insert(ArrayList *arrlst, void *data, int i);
, /* C++ */
void ArrayList_insert(ArrayList *arrlst, char *data, int i);
template< typename T, typename U >
void ArrayList_insert(ArrayList *arrlst, Buffer< T, U > &data, int i);
)
I don't think I'd do this myself, but it seems safe enough to become idiomatic.
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
I need a macro to pass the __FILE__ and __LINE__ to a function which has default arguments. This has opened up a can of worms, since default args with macros are either not possible or very messy, and I need to support both GCC and MSVC if possible:
class Class
{
#ifdef _DEBUG
int Function(int a, int b = 10, int c = 20) { return a + b + c; }
#else
int DebugFunction(const char* filename, int lineNo, int a, int b = 10, int c = 20)
{
printf("%s (%i) a:%i b:%i c:%i\n", filename, lineNo, a, b, c);
return a + b + c;
}
//Not possible
#define Function( DebugFunction(__FILE__, __LINE__
#endif
}
I've tried \escaping the ( to no avail. The codebase is huge, so fixing up the missing default args or creating multiple macros isn't a popular option.
Any solutions?
You can make a variadic macro:
#define Function(...) DebugFunction(__FILE__, __LINE__, __VA_ARGS__)
Since you cannot "overload" macros, this might be your best bet.
One option would be to rewrite your main function Function like this:
int Function(const char* filename, int lineNo, int a, int b = 10, int c = 20)
{
#ifdef _DEBUG
printf("%s (%i) a:%i b:%i c:%i\n", filename, lineNo, a, b, c);
#endif
return a + b + c;
}
That way, all the calls go to the same function, but the behavior of that function depends on whether or not you have the _DEBUG flag set. This bypasses the issue of default arguments, since you just have a normal function call with conditional code inclusion rather than a macro that might need many arguments.
Hope this helps!
I'm not quite sure I understand what you're trying to do, but would a variadic macro do the trick?
Not a big c++ guy, but have you tried something like (in pseudocode)
#ifdef debug
#define Function(args) _Function(__file__, __line__, (args))
int _Function(char *file, int line, args) { /* code */ }
#else
#define Function(args) _Function(args)
int _Function(args) { /* code */ }
#endif
The function itself needs to be able to take multiple versions of arguments, of course; I don't really see any other way of doing this.
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.