C header file won't compile with C, but will with C++ - c++

I have the following chunk of a header file BKE_mesh.h:
/* Connectivity data */
typedef struct IndexNode {
struct IndexNode *next, *prev;
int index;
} IndexNode;
void create_vert_face_map(ListBase **map, IndexNode **mem, const struct MFace *mface,
const int totvert, const int totface);
void create_vert_edge_map(ListBase **map, IndexNode **mem, const struct MEdge *medge,
const int totvert, const int totedge);
Note that the header file was prepared for the possibility of being used in a C++ file, as it had:
#ifdef __cplusplus
extern "C" {
#endif
at the top of the file, and the needed finish at the bottom. But the class implementing it was written in C.
Next, whenever I try to #include the header file, I get an odd error. If the file has a .cpp extension, it compiles just fine, no complaints whatsoever. However, if I do:
#include "BKE_mesh.h"
inside of a file with a .c extension, I get the following errors:
expected ')' before '*' token
for the two last functions, in specific, the variable:
ListBase **map
in both classes. (Note that earlier in the header file, it declared, but not defined ListBase).
So, my question is: why is this valid C++ code, but not C code?
Thank you.

In C++ you can refer to struct names directly but in C you need to prepend the keyword struct.
void create_vert_face_map(struct ListBase **map, ... );
You could get around this by adding a typedef. Then you wouldn't have to modify the function declaration.
typedef struct ListBase ListBase;

Try running just the pre-processor for each case.
Comparing the result may show different header files.
If so, it may hint on the "C"-problem.

Related

invalid application of 'sizeof' to an incomplete type

I am using an external library written in c. Our application code is written in c++.
The application code try to use an include file which contains (very simplified) the following piece of code:
#pragma once
#pragma pack(push, 1)
struct someQueue
{
struct descExtra {
unsigned int ndescs;
} desc;
};
#pragma pack(pop)
static inline void someQueue_allocate(unsigned int num)
{
unsigned int someSize = sizeof(struct someQueue) + num * sizeof(struct descExtra);
}
Now as said this is external code which I do not want to modify. When I include this header from a "C" file, it compiles. When I include this header file from a c++ file it gives me a compile error:
error: invalid application of 'sizeof' to an incomplete type descExtra
By declaring the structure inside the struct somequeue it is not accessible outside and therefore it cannot determine its size... i think? Moving this outside the somequeue struct and it will compile.
So is my understanding correct?
Why is this allowed in C but not in C++?
Can I work around this or do I need to have a c wrapper to include this header and implementation (which I not prefer..)
It's because struct descExtra is not defined. someQueue::descExtra is however defined, so instead do:
sizeof(someQueue::descExtra);
If you can't change the code to be valid for both C and C++, you might want consider using a C compiler for the C code.
This is allowed in C but not in C++ because these are two completely different programming languages.
In C++ this class is someQueue::descExtra, descExtra is a member of the someQueue class. There is no class descExtra when the shown code is parsed as C++.
One possible solution is to deploy a liberal sprinkling of
#ifdef __cplusplus
in order to supply both C and C++ alternatives.
You are partially right, In C++ when you declare nested struct, it's not accessible the same way as in C.
C code:
struct A{
struct B{};
};
int main(void){
int size = sizeof(struct B); // Compiles fine
}
But in C++, when you declare a nested structure, the structure that is not nested act like a namespace and therefore you can access the nested structure like this
C++ code:
struct A{
struct B{};
};
int main(void){
int size = sizeof(A::B); // Compiles fine
}
In C++ the "real" name of struct B is actually A::B.
The problem is that descExtra is a nested type and so when you write sizeof(struct descExtra), it declares a new class type descExtra in the enclosing scope and then we try to apply sizeof to this incomplete type which gives us the mentioned error.
A contrived example to clear this up further:
int main()
{
struct C{
struct P{};
};
//----------------vvvvvvvv--->this DECLARES a new class type called P in main()
std::cout<<sizeof(struct P);//error: invalid application of ‘sizeof’ to incomplete type ‘main()::P’
return 0;
}
So to solve this replace sizeof(struct descExtra) with sizeof(struct someQueue::descExtra)
It might be feasible to redefine struct descExtra outside the header file:
header_wrapper.h
#ifndef HEADER_WRAPPER_H__INCLUDED
#define HEADER_WRAPPER_H__INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
#pragma pack(push, 1)
struct descExtra {
unsigned int ndescs;
};
#pragma pack(pop)
#include "header.h" // defines struct someQueue, struct someQueue::descExtra, and someQueue_allocate()
#ifdef __cplusplus
}
#endif
#endif /* HEADER_WRAPPER_H__INCLUDED */
It really depends on how complicated the real struct descExtra is and what else it depends on.

Making a typedef struct externally available in c++

I think I'm doing something stupid, but I don't quite know what. I'm trying to rewrite a fairly simple library I have that is reading in some variables from a text file and then shares them with some other source files for use elsewhere. When I wanted to pass a double I was doing this:
#if !defined(SharedVariables_h)
#define SharedVariables_h
#include <vector>
extern double coeff_A;
#endif
and then doing this in both the source file where it was defined and the other source files where I want to use it:
#include "SharedVariables.h"
to make coeff_A available in the new source file.
But then my model got more complicated and I was using more coefficients so I decided to store them in a structure and pass that structure using extern instead. I created a new header file for the structure (CParameters.h):
#pragma once
#if !defined(CParameters_h)
#define CParameters_h
typedef struct
{
int coeff_A;
int coeff_B;
double coeff_C;
double coeff_D;
} SGlobalParameterData;
#endif
and then defined the struct like this:
#if !defined(SharedVariables_h)
#define SharedVariables_h
#include "CParameters.h"
#include <vector>
extern SGlobalParameterData globalParameters;
#endif
In the first source file where I read in all the values from the data files and using the values I've replaced:
#include "SharedVariables.h"
double coeff_A;
...
with
#include "SharedVariables.h"
SGlobalParameterData globalParameters;
globalParameters = readProperties(prefsFile);
....
In the second source file which also needs to use some of these variables I've added #include "SharedVariables.h" and then the IDE and compiler let me easily access globalParameters.coeff_A, globalParameters.coeff_B, etc.
I thought this should work and everything compiles without any errors, but it's not actually passing the values read into globalParameters to the second source file. Everything is just zero when I'm debugging the code.
So there are really two questions: 1) Is it possible to share structs using extern like for double, and 2) if it is, what have I done wrong.
Hopefully someone can point out my mistake.
Edit
I've added in an line of code in my example to show the function that assigns the values to the struct. This is working and the values read from the prefsFile are available and correct in the f1rst source file, but these values are not passed to source file 2. I'm going to do some more testing because it appears I may have made some other mistake elsewhere.
Your confusion stems from the use of typedef and mixing of declarations and definitions.
In C++ typedef isn't needed to define a struct type and is only confusing.
typedef struct { ... } SGlobalParameterData; - this declares a type SGlobalParameterData that is a struct. It defines no instance of the struct.
struct SGlobalParameterData { ... }; - same thing, declares a type SGlobalParameterData that is a struct.
struct { ... } globalParameterData; - this defines an object globalParameterData of an unnamed struct type.
struct SGlobalParameterData { ... } globalParameters; - this defines an object globalParameters of an struct type called SGlobalParameterData.
So... the following might be most readable/clean IMHO:
In the header:
struct SGlobalParameterData // type declaration
{
int coeff_A;
int coeff_B;
double coeff_C;
double coeff_D;
};
extern SGlobalParameterData globalParameters; // global instance *declaration*
In one of source files:
#include "the header above"
SGlobalParameterData globalParameters; // global instance *definition*
In other source files:
#include "the header above"
// globalParameters is already visible and usable
Of course you have to compile all source files and link them together into an executable.
Is it possible to share structs using extern like for double
Yes.
if it is, what have I done wrong.
Something that you haven't shown to us.
Everything is just zero
This is to be expected because variables with static storage are zero-initialised, and you never modify globalParameters in the example.
Here is your code running. Only change I made was to add some output, and actually set some other value than zero. That non-zero value works as expected: https://wandbox.org/permlink/CasO8c68W3FmBsQH

Conditional C/C++ struct definitions

I've stumbled across some code that looks like this:
typedef struct SomeStruct
{
int foo;
void * bar;
#if defined(__cplusplus)
SomeStruct();
#endif
} SomeStruct;
It's in a header file that will be included by both .c and .cpp files. That seems to be at least technically a violation of the One-Definition-Rule. The obvious impact I see is that if one of these is ever declared in .c file, the constructor won't run. And unfortunately, someone seems to have used this as a pattern for the correct way to declare structs, and has declared a couple dozen structs just like it.
I'm trying to figure out how serious a problem this is. Beyond the constructor possibly not running, is there any other likely impact? The constructor is implemented in a .cpp file. I see pointers to structs allocted in a .c file (with malloc) that are passed to functions in the .cpp files. They appear to work correctly (compiled with gcc/g++ 4.6.2 for Suse Linux, if that matters), as far as I can tell. Would something break if virtual member functions were also added? Right now, none of these classes have anything in their cplusplus section other than the default constructor, as shown above.
It's not exactly a violation of the ODR. Informally, the C compiler see a POD type and the C++ compiler see a class in the global namespace which will become an entity with a mangled name. More importantly, the structure is only declared differently for C and C++ compilers, but it is only defined once in a C++ source file. Most likely there's some allocation and free functions in a C++ source file which expose the constructor/destructor to a C API. For example,
Header file
$ cat some_struct.h
#ifndef SOME_STRUCT_H
#define SOME_STRUCT_H
typedef struct SomeStruct {
int foo;
void *var;
#if defined(__cplusplus)
SomeStruct();
#endif
} SomeStruct;
#if defined(__cplusplus)
extern "C" {
#endif
SomeStruct *some_struct_malloc();
void some_struct_free(SomeStruct **);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // SOME_STRUCT_H
C++ source file
$ cat some_struct.cpp
#include "some_struct.h"
#include <cstddef>
SomeStruct::SomeStruct()
{
foo = 10;
var = NULL;
}
SomeStruct *some_struct_malloc() { return new SomeStruct; }
void some_struct_free(SomeStruct **pp)
{
if (*pp)
delete *pp;
*pp = NULL;
}
C source file:
$ cat main.c
#include "some_struct.h"
#include <stdio.h>
int main()
{
SomeStruct *p = some_struct_malloc();
printf("%d\n", p->foo);
}
I would say it is a bad style. But it works as a convenient way to expose a C++ library to a C API

How to import a C function into C++ project that has not been declared in a C header?

I'm trying to include some functions written in C into a C++ project. I've come quite far following these instructions.
Unfortunately not all of the C functions I require to call are declared in a c header file. Some are just static functions defined inside the ".c-files".
Is there a way to still call such "non-declared-C-functions" from inside a class of my C++ project without altering the C sources (which are not maintained by myself)?
I already thought about forward declaring the C function myself in my C++ header like this:
extern "C"
{
#include "c_header_1.h"
static void c_function(int* out, const unsigned char len, const some_c_struct* st);
#include "c_header_2.h
}
gcc only reports an error:
warning: void c_function(int*, const unsigned char, const some_c_struct*); declared static but never defined [-Wunused-function].
The pointer to struct passed as 3rd parameter to c_function(int*, const unsigned char, const some_c_struct*) seems to make things even more tricky, since that type some_c_struct is declared inside the header belonging to the ".c-file" c_function(...) is declared in as well. This means I need to include the header before the forward declaration of c_function(...) but apparently this makes the linker oversee the definition.
A very simplyfied version of the C++ code looks roughly this:
Header File "CppClass.h":
#ifndef CPP_CLASS_H
#define CPP_CLASS_H
extern "C"
{
#include "c_header_1.h"
#include "c_header_2.h"
...
}
class CppClass
{
public:
//...
void some_member();
//...
};
#endif
Implementation "CppClass.cpp"
//...
void CppClass::some_member()
{
//...
::c_func_x(32, &data); // call to function in c_header_1
//...
::c_func_y(&data2); // call to function in c_header_2
::c_function(data3, len, st);
}
Clean answer: No. Functions declared static in a translation unit (.c or .cpp files typically) are not accessible anywhere else, even if you forward declare the correct function signature.
Messy answer, would not recommend: #include the offending .c file into your .cpp file and see if it works. I would consider this a hack though. Implementation files contain exactly what the name implies: implementations, not interfaces. This typically implies that you are not supposed to know about what is going on inside of it and that it might change between versions.
If you know the guy who is maintaining the sources, you could also try contacting him and ask if he could make the function part of the public interface, i.e. put it in a header and make it non-static.
I suggest that you copy the functions into a new file. Make them not static. Make a header file for them, and include that in your cpp.

Using struct in different .cpp file

I have two .cpp files in one project, main.cpp and myfile.cpp
I have globaly defined struct mystruct in main.cpp, now I want to use this struct in myfile.cpp.
When I write mystruct in a header file and include in both cpp files I get an error, saying mystruct redefinition. How should I solve this problem.
If you are trying to share the definition of a struct among several compilation units (cpp files), the common way is this: Place the definition of your struct in a header file (mystruct.h). If the struct contains any methods (i.e. it is rather a class with all member public by default), you can implement them in mystruct.CPP file, or, if they're lightweight, directly within the struct (which makes them inline by default).
mystruct.h:
#ifndef MYSTRUCT_H
#define MYSTRUCT_H
struct MyStruct
{
int x;
void f1() { /* Implementation here. */ }
void f2(); /* Implemented in mystruct.cpp */
};
#endif
mystruct.cpp
#include "mystruct.h"
// Implementation of f2() goes here
void MyStruct::f2() { ... }
You can use your struct in as many cpp files as you like, simply #include mystruct.h:
main.cpp
#include "mystruct.h"
int main()
{
MyStruct myStruct;
myStruct.x = 1;
myStruct.f2();
// etc...
}
If, on the other hand, you are trying to share a global instance of the struct across several compilation units (it's not absolutely clear from your question), do as above but also add
extern MyStruct globalStruct;
to mystruct.h. This will announce that an instance is available with external linkage; in other words that a variable exists but is initialized elsewhere (in your case in mystruct.cpp). Add the initialization of the global instance to mystruct.cpp:
MyStruct globalStruct;
This is important. Without manually creating an instance of globalStruct, you'd get unresolved-external linker errors. Now you have access to globalStruct from each compilation unit that includes mystruct.h.
You should move the common struct to a header file and include that header in both files. Any other solution is a workaround.
The problem is that you basically have the same code twice as a result if you see an include as just a import of the code.
You can use #ifdef to fix it, see http://www.fredosaurus.com/notes-cpp/preprocessor/ifdef.html
Declaration and definitions are two different things. For your case, you are allocating space for your structure in main.cpp. In your header, you should use the extern modifier for your struct so that all files that include the header file will look in the global namespace for the structure. Hope it helps.
The standard C/C++ approach:
// source.h
Put all struct, class, typedef, macro definitions, extern variable declaraltions
// source.cpp
Implement the class, functions, define global/external variables
// main.cpp, and other parts of program
#include"source.h"
You should define structure in the header file only, you should remove definition from main.cpp
May be you can give more information about what is the layout of your project.
Going by the guess, probably your problem can be either of the two:
you want forward declaration of struct.
using include guards to prevent redefinition.
See the following link for how to handle both:
http://www.adp-gmbh.ch/cpp/forward_decl.html
The header files also use include guards, so you can figure out what exactly can solve your problem.
If you want to share any variable between multiple cpp files, you should declare it in header as extern. And without extern in one of that c++ files.
If you don't do it, it'll lack at linking, because multiple objects would have variable with same name. Instead when using extern one object would have this variable and other objects link it.
The header is where you declare what your struct will consist of (probably a common.h file included by main.cpp and myfile.cpp):
struct MyStruct {
int messageID;
int tempVariable;
};
In your main.cpp, this is where you actually use the struct:
void someFunction() {
struct MyStruct tempStruct;
// do something with it
tempStruct.messageID = 1;
}
Don't put the definition of your struct in both your main.h and main.cpp - or you will get a redefinition error!
Also, don't include the cpp file - include the header file (e.g. common.h). Without knowing more about the structure of your program, it is hard to provide better information.