Typedef after incomplete type definition - c++

I'm need to declare incomplete type (may it be siginfo_t) in header, and in source import some system header (sys/signal.h), that defines that type.
So, here is the problem:
// a.h
struct siginfo_t;
void foo(siginfo_t*);
// a.cpp
#include "a.h"
#include <signal.h>
void foo(siginfo_t* x) { /* implementation */ };
But in signal.h it is defined like:
typedef struct siginfo_t { /* */ } siginfo_t;
Compiler error: error: typedef redefinition with different types ('struct siginfo_t' vs 'siginfo_t').
How to achieve no errors there? Thanks!

In the header <sys/siginfo.h> the typedef name siginfo_t is an alias for an unnamed structure
typedef struct {
int si_signo;
int si_code;
union sigval si_value;
int si_errno;
pid_t si_pid;
uid_t si_uid;
void *si_addr;
int si_status;
int si_band;
} siginfo_t;
But you introduced the same alias name for named structure
typedef struct siginfo_t { /* */ } siginfo_t;
So the compiler issues the error
error: typedef redefinition with different types ('struct siginfo_t'
vs 'siginfo_t')
because you may not introduce the same alias name for a named structure and an unnamed structure. These structures are different types.

So, there is the right approach:
// a.h
#pragma once
extern "C" {
struct siginfo;
}
void foo(siginfo*);
// a.cpp
#include "a.h"
#include <sys/siginfo.h>
void foo(siginfo* x) { /* */ };

Related

How to fix Unknown type name error with typedef struct?

Here's my code in a header file:
typedef struct _aaa
{
static void do_something(t_bbb *b); //this line is problematic
} t_aaa;
typedef struct _bbb
{
t_aaa *a;
} t_bbb;
But it says:
Unknown type name t_bbb
How can I make the code compilable?
Add a forward declaration:
struct _bbb;
typedef struct _bbb t_bbb;
typedef struct _aaa
{

Syntax Errors Testing Static Library in C++

I have a very simple setup to try to test a staticLibrary:
I get error Syntax error: Identifier MyDataT, which points me to the function declaration in MyLib.h? Any reason why struct isn't recognized in the second solution?
Here is my pseudo code:
//MSGDefs.h ==> header file only contains struct defs like this:
typedef struct __msg {
unsigned long dest;
unsigned long src;
}MsgT
typedef struct __mydata : public MsgT
{
TimeT time;
DateT date;
}MyDataT;
//======== Library generates staic lib MyLib.lib, this generates library fine=======
//MyLib.h
#include MSGdefs.h
class X{
void process(MyDataT *data);
}
//MyLib.cpp
void X::process(MyDataT *data) { // do processing here ...}
//========================================
//MyTestLibProj.cpp -- Another Solution links to MyLib.lib
#include MyLib.h ==> This causes error of identifier MyDataT ???
int main(){
// X x = new X();
}

Call function outside of current namespace in C++

I'm trying to call a function defined in a C file from my CPP code and I think I am having issues getting the correct namespace. When compiling I get the error: "Undefined reference to 'Get'".
My C header:
// c.h
#ifndef C_H
#define C_H
#ifdef __cplusplus
extern "C" {
#endif
typedef enum
{
VAL_A1,
VAL_A2
} TYPE_A;
typedef enum
{
VAL_B1,
VAL_B2
} TYPE_B;
typedef enum
{
VAL_C1,
VAL_C2
} TYPE_C;
typedef struct
{
TYPE_B b;
TYPE_C c;
} TYPE_D;
TYPE_A Get(TYPE_B b, TYPE_D *d);
#ifdef __cplusplus
}
#endif
#endif
And my CPP file:
// main.cpp
...
extern "C" {
#include "c.h"
}
...
namespace MyNamespace
{
...
MyClass::MyFunc()
{
TYPE_D d;
// None of these calls will compile
// Get(VAL_B1, &d);
// ::Get(VAL_B1, &d);
}
...
}
I have tried calling without namespace reference and also with the "root" namespace using "::" with no luck. Any help is appreciated. I've read through this which seems to clarify it but I don't really understand it:
using C++ with namespace in C
"Undefined reference" means that the function has been declared (in the header), but not defined. You'll need to define the function in a source file somewhere (presumably the C file you refer to), and make sure that is linked when you build the program.
First, let's note what that error means. An undefined reference at the linker stage means that the compiler is unable to find the instance of something. In this case, the implementation of a function.
Let's look at your code.. There are a few things missing that we need to add to make it compilable:
A definition for Get().
main()
The class definition for MyClass.
Once we added those three fixes, the code compiles without error.
extern "C" { extern "C" {
typedef enum {
VAL_A1,
VAL_A2
} TYPE_A;
typedef enum {
VAL_B1,
VAL_B2
} TYPE_B;
typedef enum {
VAL_C1,
VAL_C2
} TYPE_C;
typedef struct {
TYPE_B b;
TYPE_C c;
} TYPE_D;
TYPE_A Get(TYPE_B b, TYPE_D *d) {
return VAL_A1;
}
}}
namespace MyNamespace {
struct MyClass {
void MyFunc();
};
void MyClass::MyFunc() {
TYPE_D d;
Get(VAL_B1, &d);
::Get(VAL_B1, &d);
}
}
int main() {}
The definition of Get (not shown in the question) also needs to be enclosed in extern "C".
The main difference between C and C++ functions, in practice, is the way they are named in the executable format. C++ functions get "name mangling" treatment by the linker but C functions do not. The linker will see the C++ definition of Get and it will have no idea of its relation to the C declaration, even if they have the same signature.

Opaque pointer in MSVC generates compiler error

main.c
#include "stackg.h"
int main()
{
return 0;
}
stackg.h
#ifndef STACKG_H
#define STACKG_H
#ifdef __cplusplus
extern "C" {
#endif
typedef struct stack_gt* stack_gt;
stack_gt stkg_init(
void* (*alloc)(const void* data, const int size),
void (*dealloc)(void* data),
void (*copy)(void* data_d, const void* data_s),
const int size
);
void stkg_free(stack_gt s);
int stkg_is_empty(stack_gt s);
int stkg_is_full(stack_gt s);
const int stkg_size(const stack_gt s);
void stkg_clear(stack_gt s);
int stkg_push(stack_gt s, const void* data);
int stkg_pop(stack_gt s, void* data);
int stkg_peek(stack_gt s, void* data);
#ifdef __cplusplus
}
#endif
#endif
The above program compiles successfully with the GCC compiler, but in MSVC2008 it gives the following error :
error C2040: 'stack_gt *' differs in levels of indirection from 'stack_gt'
What should I tell MSVC to make it compile the program without changing anything in the code?
Edit
Error occurs at line 8 of stackg.h :: typedef struct stack_gt* stack_gt;
Edit 2
If nothing else, I'll go with typedef struct _stack_gt* stack_gt;
The problem is that here:
typedef struct stack_gt* stack_gt;
you are giving stack_gt a different type, while this works fine:
typedef struct stack_gt* stack_gtB;
clang gives us a nicer error message:
error: typedef redefinition with different types ('struct stack_gt *' vs 'stack_gt')
This is covered in the draft C++ standard section 7.1.3 The typedef specifier paragraph 6:
In a given scope, a typedef specifier shall not be used to redefine the name of any type declared in that scope to refer to a different type. [ Example:
class complex { / ... / };
typedef int complex; // error: redefinition
—end example ]
Using the same name though is fine, so this would be ok:
typedef struct stack_gt stack_gt;
covered in paragraph 3:
In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers. [ Example:
typedef struct s { / ... / } s;
typedef int I;
typedef int I;
typedef I I;
—end example ]
Another idea:
#ifdef __cplusplus
extern "C" {
typedef void * stack_gt
#else
typedef struct stack_gt* stack_gt;
#endif
This is ugly, but you don't need to rewrite any other part of the code, only this header included in C++ . It is only used as an opaque pointer in C++ anyways, and C doesn't notice.

Errror with typedef: too few template-parameter-lists

I've seen some responses to the too few template-parameter-lists problem in classes but I'm getting a similar error in a header file where the declarations seem to be at the name space level. I'm not at all a C++ guy, but I want to figure out what I need to correct in this file to prevent the following error regarding the two lines after the typedef:
too few template-parameter-lists
Here's a file experpt
#ifndef SH_AUDATA_H
#define SH_AUDATA_H
#include "BinaryIO.h"
#include "AudioData.h"
// AuMuLawAudioData
typedef AudioDataImpl<AuMuLaw,BYTE> AuMuLawAudioData ;
inline BYTE AuMuLawAudioData::readValue (BinaryIO* io) const { return (io->read8()) ; }
inline void AuMuLawAudioData::writeValue (BinaryIO* io, BYTE v) const { io->write8(v) ; }
#endif // ndef SH_AUDATA_H
Thanks!
You either need to
indicate your defining a template member using template<> (http://ideone.com/ZWYuCd)
or you should just use the full qualified class name (http://ideone.com/zsmHjG)
Contrast both:
template <typename T> struct X
{
T v;
void foo();
};
typedef X<int> SomeTypedef;
#if 0
template<> void SomeTypedef::foo() {
//
}
#else
template <typename T> void X<T>::foo() {
//
}
#endif
int main()
{
SomeTypedef a;
a.foo();
}
Both the approaches to define foo will work (change #if 0 to #if 1 to "select" the other approach)