Using operator new in mixed c and c++ code - c++

Consider a program with mixed C and C++ code. The C++ part contains a class which dinamically allocates a C-style typedef struct. Minimal example:
obj.h (C-code)
typedef struct _Ctype {
int i;
} Ctype;
class.hpp (C++ code)
struct A {
struct _Ctype *x;
A(int i);
~A();
};
class.cpp (C++ code)
#include "class.hpp"
extern "C" {
#include "obj.h"
}
A::A(int i)
{
x = new struct _Ctype;
x->i = i;
}
A::~A()
{
delete(x);
}
main.cpp (C++ code, main program)
#include "class.hpp"
int main()
{
A a(3);
return 0;
}
(The rationale for this design originates from this answer)
Is it safe (i.e., no UB) to use a new expression to allocate a C-style type struct _Ctype, as in the code above, or should one better use the C-style malloc/free?
class.cpp (C++ code, alternative)
#include <cstdlib>
#include "class.hpp"
extern "C" {
#include "obj.h"
}
A::A(int i)
{
x = (struct _Ctype *)malloc(sizeof(struct _Ctype));
x->i = i;
}
A::~A()
{
free(x);
}
ADDITION
To clarify the question after some comments below: In the minimal example above, all the code is compiled with a C++ compiler. One can however think to use the C++ code in conjunction with a C library. The question can then be reformulated as follows:
If I allocate memory for an C-style typedef struct via a C++ code, can the C library safely use the allocated variable? If so, are the alternatives given above both safe?
Note that one could also think to allocate the memory for Ctype through a C function, so that the C++ code only manages a pointer to it, for example:
obj.h (C-code)
typedef struct _Ctype {
int i;
} Ctype;
Ctype *allocate_Ctype();
void deallocate_Ctype(Ctype* p);
obj.C (C-code)
#include <stdlib.h>
#include "obj.h"
Ctype *allocate_Ctype()
{
return (Ctype *)malloc(sizeof(Ctype));
}
void deallocate_Ctype(Ctype *p)
{
free(p);
}
class.cpp (C++ code)
#include "class.hpp"
extern "C" {
#include "obj.h"
}
A::A(int i)
{
x = allocate_Ctype();
x->i = i;
}
A::~A()
{
deallocate_Ctype(x);
}
(Note: of course the copy constructor and operator assignment of class A need to be properly defined, the code serves as illustration of the question)

As long as the deallocation only ever happens under your control and using a delete expression, there is no problem at all. The C code interacting with the structure does not care how it was allocated.
Side note: the name _Ctype is not legal in C++, as it starts with an underscore followed by an uppercase letter. Such names (as well as names containing double underscore) are reserved for the compiler & standard library.

Related

How to wrap std::vector to use in pure C

In my project I would like to use C++ and STL containers but have a problem that I have to include hw vendor headers (and link vendor lib and use some vendor C sources that also include the vendor headers) written in ANSI C, that contain C++ reserved keywords, for example:
vendor.h:
// Vendor header (read only)
struct Vendor_Export_Struct {
unsigned char* data;
};
struct Vendor_Export_Struct export; // <<< compilation error under C++
union Vendor_Union {
struct Vendor_Export_Struct export; // <<< compilation error under C++
};
What included into C++ will cause errors during compile: expected unqualified id before ‘export’. So I'm forced to use pure C and thinking if it would be possible simply wrap STL vector to kind of C API like this (with C++ implementation behind):
cvect.h :
typedef void* Vect_Type;
typedef void** Vect_Iterator_Type;
typedef void* Vect_Data_Type;
Vect_Type Vect_New();
void Vect_PushBack(Vect_Type v, Vect_Data_Type d);
Vect_Iterator_Type Vect_Begin(Vect_Type v);
Vect_Iterator_Type Vect_End(Vect_Type v);
Vect_Iterator_Type Vect_Next(Vect_Type v, Vect_Iterator_Type it);
But problem is how to pass on the vector and iterator. I think I would be forced to use reinterpret_cast when casting from std::vector<> -> void* -> std::vector<> on the C++ code side and still thinking how to cast/pass std::vector<>::iterator.
c_vect.cpp :
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include "c_vect.h"
typedef std::vector<void*> Vect_Container_Type;
Vect_Type Vect_New()
{
return static_cast<Vect_Type>(new Vect_Container_Type);
}
void Vect_PushBack(Vect_Type v, Vect_Data_Type d)
{
Vect_Container_Type& vref = *reinterpret_cast<Vect_Container_Type*>(v);
vref.push_back(d);
}
Vect_Iterator_Type Vect_Begin(Vect_Type v)
{
Vect_Container_Type& vref = *reinterpret_cast<Vect_Container_Type*>(v);
return &*vref.begin();
}
Vect_Iterator_Type Vect_End(Vect_Type v)
{
Vect_Container_Type& vref = *reinterpret_cast<Vect_Container_Type*>(v);
return &*vref.end();
}
Vect_Iterator_Type Vect_Next(Vect_Type v, Vect_Iterator_Type it)
{
Vect_Container_Type& vref = *reinterpret_cast<Vect_Container_Type*>(v);
Vect_Container_Type::iterator it_ = static_cast<Vect_Container_Type::iterator>(it); //<<<< ugly and not portable
if (it_ != vref.end())
{
++it_;
return &*it_;
}
return NULL;
}
main.c :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "c_vect.h"
#include "vendor.h"
typedef struct S_Connection {
size_t id;
char* name;
union Vendor_Union u;
Vect_Type sessions; // Another vector
} T_Connection;
typedef T_Connection* T_ConnectionPtr;
static void* makeConn(size_t id, const char* name)
{
T_ConnectionPtr ptr = (T_ConnectionPtr)malloc(sizeof(T_Connection));
ptr->id = id;
ptr->name = (char*)malloc(strlen(name) + 1);
strcpy(ptr->name, name);
return ptr;
}
int main(int argc, char* argv[])
{
Vect_Type conns = Vect_New();
Vect_Iterator_Type it;
unsigned i;
for (i = 0; i < 10; ++i) {
char name[20];
sprintf(name, "conn_%03d", i);
Vect_PushBack(conns, makeConn(i + 1, name));
}
// Iterate vector and access stored data
for (it = Vect_Begin(conns);
it != Vect_End(conns);
it = Vect_Next(conns, it)) {
T_ConnectionPtr cd = (T_ConnectionPtr)*it;
}
return 0;
}
So I'm not sure if all this is a good idea, probably not from several reasons. I just would like to avoid another redundant C vector implementation, take profit from STL iterators. The final code should be portable. Has someone been solving a similar problem like this? Or do you have a better idea how to cope with this?
There are methods now to access the raw data array of the Vector:
value_type* data() noexcept;
const value_type* data() const noexcept;
These extensions were added in C++11 exactly for your case, to interface third party libraries that only take the raw data array. Pass the returned pointer to C as an array that is also a pointer in C. You will likely need add vector.size() as another parameter.
Do not manipulate the vector while using the returned pointer.
I am by no means an expert in this topic, but I've run into this problem before, and I've found that there are two options that seem to work:
You can write a vector library in C yourself. I've often found that this isn't really as hard as it may seem, and then you don't have code that is reliant upon the C++ STL, which won't be supported in a lot of the places one may want to use C, like in embedded systems, for example.
You will have to make a header in the following form:
#ifdef __cplusplus
extern "C" {
#endif
/* Define all your C wrapper functions here */
/* For example: */
void VectorWrapper_Add(struct VectorWrapper *vector_wrapper, const struct VectorWrapper_DataType *data_to_add);
#ifdef __cplusplus
}
#endif
And then in the implementation file, you can put something like this:
#include "my_c_wrapper.h"
#include <vector>
/* Do something similar for all your functions... */
void VectorWrapper_Add(struct VectorWrapper *vector_wrapper, const struct VectorWrapper_DataType *data_to_add)
{
/* Your implementation might look something like this for such a function: */
vector_wrapper->_stl_vector->push_back(*data_to_add);
}
Most the time, what I end up doing is just creating my own libraries to manage these sorts of data structures; but again, the choice is yours.
I hope my answer helps you.

C wrapper for C++ class with stack allocation

Let's say we have a C++ library with a class like this:
class TheClass {
public:
TheClass() { ... }
void magic() { ... }
private:
int x;
}
Typical usage of this class would include stack allocation:
TheClass object;
object.magic();
We need to create a C wrapper for this class. The most common approach looks like this:
struct TheClassH;
extern "C" struct TheClassH* create_the_class() {
return reinterpret_cast<struct TheClassH*>(new TheClass());
}
extern "C" void the_class_magic(struct TheClassH* self) {
reinterpret_cast<TheClass*>(self)->magic();
}
However, it requires heap allocation, which is clearly not desired for such a small class.
I'm searching for an approach to allow stack allocation of this class from C code. Here is what I can think of:
struct TheClassW {
char space[SIZEOF_THECLASS];
}
void create_the_class(struct TheClassW* self) {
TheClass* cpp_self = reinterpret_cast<TheClass*>(self);
new(cpp_self) TheClass();
}
void the_class_magic(struct TheClassW* self) {
TheClass* cpp_self = reinterpret_cast<TheClass*>(self);
cpp_self->magic();
}
It's hard to put real content of the class in the struct's fields. We can't just include C++ header because C wouldn't understand it, so it would require us to write compatible C headers. And this is not always possible. I think C libraries don't really need to care about content of structs.
Usage of this wrapper would look like this:
TheClassW object;
create_the_class(&object);
the_class_magic(&object);
Questions:
Does this approach have any dangers or drawbacks?
Is there an alternative approach?
Are there any existing wrappers that use this approach?
You can use placement new in combination of alloca to create an object on the stack. For Windows there is _malloca. The importance here is that alloca, and malloca align memory for you accordingly and wrapping the sizeof operator exposes the size of your class portably. Be aware though that in C code nothing happens when your variable goes out of scope. Especially not the destruction of your object.
main.c
#include "the_class.h"
#include <alloca.h>
int main() {
void *me = alloca(sizeof_the_class());
create_the_class(me, 20);
if (me == NULL) {
return -1;
}
// be aware return early is dangerous do
the_class_magic(me);
int error = 0;
if (error) {
goto fail;
}
fail:
destroy_the_class(me);
}
the_class.h
#ifndef THE_CLASS_H
#define THE_CLASS_H
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
class TheClass {
public:
TheClass(int me) : me_(me) {}
void magic();
int me_;
};
extern "C" {
#endif
size_t sizeof_the_class();
void *create_the_class(void* self, int arg);
void the_class_magic(void* self);
void destroy_the_class(void* self);
#ifdef __cplusplus
}
#endif //__cplusplus
#endif // THE_CLASS_H
the_class.cc
#include "the_class.h"
#include <iostream>
#include <new>
void TheClass::magic() {
std::cout << me_ << std::endl;
}
extern "C" {
size_t sizeof_the_class() {
return sizeof(TheClass);
}
void* create_the_class(void* self, int arg) {
TheClass* ptr = new(self) TheClass(arg);
return ptr;
}
void the_class_magic(void* self) {
TheClass *tc = reinterpret_cast<TheClass *>(self);
tc->magic();
}
void destroy_the_class(void* self) {
TheClass *tc = reinterpret_cast<TheClass *>(self);
tc->~TheClass();
}
}
edit:
you can create a wrapper macro to avoid separation of creation and initialization. you can't use do { } while(0) style macros because it will limit the scope of the variable. There is other ways around this but this is highly dependent on how you deal with errors in the code base. A proof of concept is below:
#define CREATE_THE_CLASS(NAME, VAL, ERR) \
void *NAME = alloca(sizeof_the_class()); \
if (NAME == NULL) goto ERR; \
// example usage:
CREATE_THE_CLASS(me, 20, fail);
This expands in gcc to:
void *me = __builtin_alloca (sizeof_the_class()); if (me == __null) goto fail; create_the_class(me, (20));;
There are alignment dangers. But maybe not on your platform. Fixing this may require platform specific code, or C/C++ interop that is not standardized.
Design wise, have two types. In C, it is struct TheClass;. In C++, struct TheClass has a body.
Make a struct TheClassBuff{char buff[SIZEOF_THECLASS];};
TheClass* create_the_class(struct TheClassBuff* self) {
return new(self) TheClass();
}
void the_class_magic(struct TheClass* self) {
self->magic();
}
void the_class_destroy(struct TheClass* self) {
self->~TheClass();
}
C is supposed to make the buff, then create a handle from it and interact using it. Now usually that isn't required as reinterpreting pointer to theclassbuff will work, but I think that is undefined behaviour technically.
Here is another approach, which may or may not be acceptable, depending on the application specifics. Here we basically hide the existence of TheClass instance from C code and encapsulate every usage scenario of TheClass in a wrapper function. This will become unmanageable if the number of such scenarios is too large, but otherwise may be an option.
The C wrapper:
extern "C" void do_magic()
{
TheClass object;
object.magic();
}
The wrapper is trivially called from C.
Update 2/17/2016:
Since you want a solution with a stateful TheClass object, you can follow the basic idea of your original approach, which was further improved in another answer. Here is yet another spin on that approach, where the size of the memory placeholder, provided by the C code, is checked to ensure it is sufficiently large to hold an instance of TheClass.
I would say that the value of having a stack-allocated TheClass instance is questionable here, and it is a judgement call depending on the application specifics, e.g. performance. You still have to call the de-allocation function, which in turn calls the destructor, manually, since it is possible that TheClass allocates resources that have to be released.
However, if having a stack-allocated TheClass is important, here is another sketch.
The C++ code to be wrapped, along with the wrapper:
#include <new>
#include <cstring>
#include <cstdio>
using namespace std;
class TheClass {
public:
TheClass(int i) : x(i) { }
// cout doesn't work, had to use puts()
~TheClass() { puts("Deleting TheClass!"); }
int magic( const char * s, int i ) { return 123 * x + strlen(s) + i; }
private:
int x;
};
extern "C" TheClass * create_the_class( TheClass * self, size_t len )
{
// Ensure the memory buffer is large enough.
if (len < sizeof(TheClass)) return NULL;
return new(self) TheClass( 3 );
}
extern "C" int do_magic( TheClass * self, int l )
{
return self->magic( "abc", l );
}
extern "C" void delete_the_class( TheClass * self )
{
self->~TheClass(); // 'delete self;' won't work here
}
The C code:
#include <stdio.h>
#define THE_CLASS_SIZE 10
/*
TheClass here is a different type than TheClass in the C++ code,
so it can be called anything else.
*/
typedef struct TheClass { char buf[THE_CLASS_SIZE]; } TheClass;
int do_magic(TheClass *, int);
TheClass * create_the_class(TheClass *, size_t);
void delete_the_class(TheClass * );
int main()
{
TheClass mem; /* Just a placeholder in memory for the C++ TheClass. */
TheClass * c = create_the_class( &mem, sizeof(TheClass) );
if (!c) /* Need to make sure the placeholder is large enough. */
{
puts("Failed to create TheClass, exiting.");
return 1;
}
printf("The magic result is %d\n", do_magic( c, 232 ));
delete_the_class( c );
return 0;
}
This is just a contrived example for illustration purposes. Hopefully it is helpful. There may be subtle problems with this approach, so testing on your specific platform is highly important.
A few additional notes:
THE_CLASS_SIZE in the C code is just the size of a memory buffer in which
a C++'s TheClass instance is to be allocated; we are fine as long as
the size of the buffer is sufficient to hold a C++'s TheClass
Because TheClass in C is just a memory placeholder, we might just as
well use a void *, possibly typedef'd, as the parameter type in the
wrapper functions instead of TheClass. We would reinterpret_cast
it in the wrapper code, which would actually make the code clearer:
pointers to C's TheClass are essentially reinterpreted as C++'s TheClass anyway.
There is nothing to prevent C code from passing a TheClass* to the
wrapper functions that doesn't actually point to a C++'s TheClass
instance. One way to solve this is to store pointers to properly
initialized C++ TheClass instances in some sort of a data structure
in the C++ code and return to the C code handles that can be used to
look up these instances.
To use couts in the C++ wrapper we need to link with
the C++ standard lib when building an executable. For example, if
the C code is compiled into main.o and C++ into lib.o, then on
Linux or Mac we'd do gcc -o junk main.o lib.o -lstdc++.
It worth to keep each piece of knowledge in a single place, so I would suggest to make a class code "partially readable" for C. One may employ rather simple set of macro definitions to enable it to be done in short and standard words. Also, a macro may be used to invoke constructor and destructor at the beginning and the end of stack-allocated object's life.
Say, we include the following universal file first into both C and C++ code:
#include <stddef.h>
#include <alloca.h>
#define METHOD_EXPORT(c,n) (*c##_##n)
#define CTOR_EXPORT(c) void (c##_construct)(c* thisPtr)
#define DTOR_EXPORT(c) void (c##_destruct)(c* thisPtr)
#ifdef __cplusplus
#define CL_STRUCT_EXPORT(c)
#define CL_METHOD_EXPORT(c,n) n
#define CL_CTOR_EXPORT(c) c()
#define CL_DTOR_EXPORT(c) ~c()
#define OPT_THIS
#else
#define CL_METHOD_EXPORT METHOD_EXPORT
#define CL_CTOR_EXPORT CTOR_EXPORT
#define CL_DTOR_EXPORT DTOR_EXPORT
#define OPT_THIS void* thisPtr,
#define CL_STRUCT_EXPORT(c) typedef struct c c;\
size_t c##_sizeof();
#endif
/* To be put into a C++ implementation coce */
#define EXPORT_SIZEOF_IMPL(c) extern "C" size_t c##_sizeof() {return sizeof(c);}
#define CTOR_ALIAS_IMPL(c) extern "C" CTOR_EXPORT(c) {new(thisPtr) c();}
#define DTOR_ALIAS_IMPL(c) extern "C" DTOR_EXPORT(c) {thisPtr->~c();}
#define METHOD_ALIAS_IMPL(c,n,res_type,args) \
res_type METHOD_EXPORT(c,n) args = \
call_method(&c::n)
#ifdef __cplusplus
template<class T, class M, M m, typename R, typename... A> R call_method(
T* currPtr, A... args)
{
return (currPtr->*m)(args...);
}
#endif
#define OBJECT_SCOPE(t, v, body) {t* v = alloca(t##_sizeof()); t##_construct(v); body; t##_destruct(v);}
Now we can declare our class (the header is useful both in C and C++, too)
/* A class declaration example */
#ifdef __cplusplus
class myClass {
private:
int y;
public:
#endif
/* Also visible in C */
CL_STRUCT_EXPORT(myClass)
void CL_METHOD_EXPORT(myClass,magic) (OPT_THIS int c);
CL_CTOR_EXPORT(myClass);
CL_DTOR_EXPORT(myClass);
/* End of also visible in C */
#ifdef __cplusplus
};
#endif
Here is the class implementation in C++:
myClass::myClass() {std::cout << "myClass constructed" << std::endl;}
CTOR_ALIAS_IMPL(myClass);
myClass::~myClass() {std::cout << "myClass destructed" << std::endl;}
DTOR_ALIAS_IMPL(myClass);
void myClass::magic(int n) {std::cout << "myClass::magic called with " << n << std::endl;}
typedef void (myClass::* myClass_magic_t) (int);
void (*myClass_magic) (myClass* ptr, int i) =
call_method<myClass,myClass_magic_t,&myClass::magic,void,int>;
and this is a using C code example
main () {
OBJECT_SCOPE(myClass, v, {
myClass_magic(v,178);
})
}
It's short and working! (here's the output)
myClass constructed
myClass::magic called with 178
myClass destructed
Note that a variadic template is used and this requires c++11. However, if you don't want to use it, a number of fixed-size templates ay be used instead.
Here's how one might do it safely and portably.
// C++ code
extern "C" {
typedef void callback(void* obj, void* cdata);
void withObject(callback* cb, void* data) {
TheClass theObject;
cb(&theObject, data);
}
}
// C code:
struct work { ... };
void myCb (void* object, void* data) {
struct work* work = data;
// do whatever
}
// elsewhere
struct work work;
// initialize work
withObject(myCb, &work);
What I did in alike situation is something like:
(I omit static_cast, extern "C")
class.h:
class TheClass {
public:
TheClass() { ... }
void magic() { ... }
private:
int x;
}
class.cpp
<actual implementation>
class_c_wrapper.h
void* create_class_instance(){
TheClass instance = new TheClass();
}
void delete_class_instance(void* instance){
delete (TheClass*)instance;
}
void magic(void* instance){
((TheClass*)instance).magic();
}
Now, you stated that you need stack allocation. For this I can suggest rarely used option of new: placement new. So you'd pass additional parameter in create_class_instance() that is pointing to an allocated buffer enough to store class instance, but on stack.
This is how I would solve the issue (basic idea is to let interprete C and C++ the same memory and names differently):
TheClass.h:
#ifndef THECLASS_H_
#define THECLASS_H_
#include <stddef.h>
#define SIZEOF_THE_CLASS 4
#ifdef __cplusplus
class TheClass
{
public:
TheClass();
~TheClass();
void magic();
private:
friend void createTheClass(TheClass* self);
void* operator new(size_t, TheClass*) throw ();
int x;
};
#else
typedef struct TheClass {char _[SIZEOF_THE_CLASS];} TheClass;
void create_the_class(struct TheClass* self);
void the_class_magic(struct TheClass* self);
void destroy_the_class(struct TheClass* self);
#endif
#endif /* THECLASS_H_ */
TheClass.cpp:
TheClass::TheClass()
: x(0)
{
}
void* TheClass::operator new(size_t, TheClass* self) throw ()
{
return self;
}
TheClass::~TheClass()
{
}
void TheClass::magic()
{
}
template < bool > struct CompileTimeCheck;
template < > struct CompileTimeCheck < true >
{
typedef bool Result;
};
typedef CompileTimeCheck< SIZEOF_THE_CLASS == sizeof(TheClass) >::Result SizeCheck;
// or use static_assert, if available!
inline void createTheClass(TheClass* self)
{
new (self) TheClass();
}
extern "C"
{
void create_the_class(TheClass* self)
{
createTheClass(self);
}
void the_class_magic(TheClass* self)
{
self->magic();
}
void destroy_the_class(TheClass* self)
{
self->~TheClass();
}
}
The createTheClass function is for friendship only - I wanted to avoid the C wrapper functions to be publicly visible within C++. I caught up the array variant of the TO, because I consider this better readable than the alloca approach. Tested with:
main.c:
#include "TheClass.h"
int main(int argc, char*argv[])
{
struct TheClass c;
create_the_class(&c);
the_class_magic(&c);
destroy_the_class(&c);
}

Is there some other way of executing this example in isocpp.org?

I tried to compile and link the second example (see below), in the second FAQ in this link in isocpp.org.
Naturally, this works only for non-member functions. If you want to
call member functions (incl. virtual functions) from C, you need to
provide a simple wrapper. For example:
// C++ code:
class C {
// ...
virtual double f(int);
};
extern "C" double call_C_f(C* p, int i) // wrapper function
{
return p->f(i);
}
Now C::f() can be used like this:
/* C code: */
double call_C_f(struct C* p, int i);
void ccc(struct C* p, int i)
{
double d = call_C_f(p,i);
/* ... */
}
After several trials, I succeeded executing the example in VS2015. But I'm still not convinced about the declaration extern "C" struct C *p = &c; that I had to use in other.cpp (I simply couldn't make the code to work with anything different than this). Note that the C++ compiler emits the following warning for the alluded declaration:
warning C4099: 'C': type name first seen using 'class' now seen using
'struct'
main.c was compiled with the C compiler and other.cpp with the C++ compiler.
main.c
/* C code: */
#include <stdio.h>
extern struct C *p;
double call_C_f(struct C* p, int i);
void ccc(struct C* p, int i)
{
double d = call_C_f(p, i);
printf("%f", d);
}
int main()
{
ccc(p, 1);
}
other.cpp
// C++ code:
class C {
public:
virtual double f(int i) { return i; };
} c;
extern "C" struct C *p = &c; // This is the declaration that I'm concerned about
// Is it correct?
extern "C" double call_C_f(C* p, int i) // wrapper function
{
return p->f(i);
}
The line extern "C" struct C *p = &c is IMHO more confusing than really useful. In the same C++ compilation unit you first declare C to be a class, then a struct. As already said in comment with refs in that other question, declaring a class once with struct and once with class may lead to mangling issues in C++ code.
And it is useless, because as C is not a POD struct (it contains method and even a virtual one) it cannot be used from C as a struct, and in fact you only use a pointer to C from c code as an opaque pointer.
So the line should be written:
extern "C" class C *p = &c;
declaring to the compiler that you are defining a pointer to class C with extern linkage named p, pointing to c. Perfectly defined from C++ perspective.
Next from C point of view, you declare the extern pointer p, pointing to an undefined struct C. C will only allow you to use it almost a void pointer, meaning you can affect it and pass it to function, but p->xxx would cause an error because struct C is not fully declared in that compilation unit.
In fact the following code does exactly the same as yours without any warning:
main.c
/* C code: */
#include <stdio.h>
extern struct D *p;
double call_C_f(struct D* p, int i);
void ccc(struct D* p, int i)
{
double d = call_C_f(p, i);
printf("%f", d);
}
int main()
{
ccc(p, 1);
return 0; /* never return random value to environment */
}
other.cpp
// C++ code:
class C {
public:
virtual double f(int i) { return i; };
} c;
extern "C" C *p = &c;
extern "C" double call_C_f(C* p, int i) // wrapper function
{
return p->f(i);
}
The usage of struct D is not a typo. Of course I should have used struct C to avoid confusion for the reader, but it is not a problem for the compiler not for the linker: p in main.c is just a pointer to an opaque not fully declared struct. That's the reason why, it is common to declare such opaque pointers as void *.

Returning array of character error in c++?

I have these two files table.cpp and table.h in my program code apart from the main.cpp. The files are described as below
table.cpp
#include <iostream>
#include "table.h"
using namespace std;
// accessor function for Name
char* PeriodicTable::Name()
{
return Name;
}
// accessor function for Symbol
char* PeriodicTable::Symbol()
{
return Symbol;
}
table.h
#ifndef TABLE_H
#define TABLE_H
class PeriodicTable
{
char Name[15], Symbol[3], GroupName[20], Block, State[25], Colour[15], Classification[20];
int GroupNo, AtomicNo, PeriodNo;
float Weight;
public:
char* Name();
char* Symbol();
};
#endif
but the problem is that the IntelliSense(since I am using Visual C++ Express 2010) shows a red curved underline below the name and symbol in the accessor function in table.cpp. I can't understand why???
Your member functions and member variables have the same name. This is not possible in C++. That's why various conventions exist for naming member variables, e.g. m_name, name_ etc. (NB: When dealing with underscores in identifiers make sure you don't use a reserved name by accident.)
You might wonder why and how that could possibly go wrong. In your example there clearly is no way to invoke operator() on char[15], but the problem is that the compiler only knows that after performing semantic analysis. There could also be cases where it is impossible to disambiguate. For example:
struct Func {
void operator()() { };
};
struct C {
Func f;
void f() {}
};
int main() {
C c;
c.f(); // which one?
}

Strange issue using RWTValHashMap with g++ on Linux

I am writing a simple test program on Linux system by using g++ 4.3 and Rogue Wave library. The problem that I am facing here is that the following codes can be compiled but it would pop up a segmentation fault on this line when I run it:
_aClasses.insertKeyAndValue(100,1000);
When I run the same piece code on a HPUX machine by using aCC compiler. It runs smoothly which makes me confused. Is that because the way that g++ initialize the static variable is different from aCC does? Anyone knows what's going on here? Thanks in advance.
A.hxx
#include <rw/tvhdict.h>
#include <rw/cstring.h>
#include <rw/rwdate.h>
#include <rw/rstream.h>
using namespace std;
class A
{
public :
A();
static void add();
struct long_hash {
unsigned long operator() (const long& x) const { return x;};
};
struct long_equal {
RWBoolean operator() (const long& x, const long& y) const { return x==y;};
};
private:
static RWTValHashMap<long, long, long_hash, long_equal> _aClasses;
};
A.cxx
#include "A.hxx"
RWTValHashMap<long, long, A::long_hash, A::long_equal> A::_aClasses;
A::A()
{
cout<<"init A"<<endl;
}
void A::add()
{
_aClasses.insertKeyAndValue(100,1000);
}
B.hxx
class B
{
public:
B();
};
B.cxx
#include "B.hxx"
#include "A.hxx"
B::B()
{
A::add();
}
Main.cxx
#include "A.hxx"
#include "B.hxx"
static B c;
int main() {
cout<<"main"<<endl;
return 0;
}
The order of initialization of static members from different translation units (essentially different cpp/cxx files) is not specified. So whether static B c or RWTValHashMap<long, long, A::long_hash, A::long_equal> A::_aClasses will be initialized first can be different for different compilers and may even change when using the same compiler. It was simply luck that your previous compiler always initialized them in the desired order.
A way to avoid this is to use the 'construct on first use idiom'