Syntax Errors Testing Static Library in C++ - 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();
}

Related

Why the compiler is generating errors which aren't errors at all

I was trying to write my own VM implementation in C++ from the excellent book Crafting Interpreters.
The book builds a stack based virtual machine, of which I am writing a C++ version
So here is the code where the compiler is yelling at me.
object.h
#pragma once
#include "common.h"
#include "value.h"
#include "chunk.h"
#define OBJ_TYPE(value) (AS_OBJ(value)->type)
#define IS_CLOSURE(value) isObjType(value, OBJ_CLOSURE)
#define IS_FUNCTION(value) isObjType(value, OBJ_FUNCTION)
#define IS_NATIVE(value) isObjType(value, OBJ_NATIVE)
#define IS_STRING(value) isObjType(value, OBJ_STRING)
#define AS_CLOSURE(value) ((ObjClosure*)AS_OBJ(value))
#define AS_FUNCTION(value) ((ObjFunction*)AS_OBJ(value))
#define AS_NATIVE(value) (((ObjNative*)AS_OBJ(value))->function)
#define AS_STRING(value) ((ObjString*)AS_OBJ(value))
#define AS_CSTRING(value) (((ObjString*)AS_OBJ(value))->chars)
typedef enum {
OBJ_CLOSURE,
OBJ_FUNCTION,
OBJ_NATIVE,
OBJ_STRING,
OBJ_UPVALUE
} ObjType;
struct Obj {
ObjType type;
Obj* next;
};
struct ObjString :Obj {
int length;
char* chars;
uint32_t hash;
};
struct ObjFunction :Obj {
int arity;
int upvalueCount;
Chunk chunk;
ObjString* name;
};
struct ObjUpvalue :Obj {
Value* location;
};
struct ObjClosure :Obj {
ObjFunction* function;
ObjUpvalue** upvalues;
int upvalueCount;
};
typedef Value(*NativeFn)(int, Value*);
struct ObjNative :Obj {
NativeFn function;
};
ObjUpvalue* newUpvalue(Value* slot);
ObjClosure* newClosure(ObjFunction* function);
ObjFunction* newFunction();
ObjNative* newNative(NativeFn function);
ObjString* takeString(char* chars, int length);
ObjString* copyString(const char* chars, int length);
void printObject(Value value);
static inline bool isObjType(Value value, ObjType type) {
return IS_OBJ(value) && AS_OBJ(value)->type == type;
}
common.h
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#define DEBUG_PRINT_CODE
#define DEBUG_TRACE_EXECUTION
#define UINT8_COUNT (UINT8_MAX + 1)
value.h
#pragma once
#include "common.h"
#include "object.h"
typedef enum {
VAL_BOOL,
VAL_NIL,
VAL_NUMBER,
VAL_OBJ
} ValueType;
#define IS_BOOL(value) ((value).type == VAL_BOOL)
#define IS_NIL(value) ((value).type == VAL_NIL)
#define IS_NUMBER(value) ((value).type == VAL_NUMBER)
#define IS_OBJ(value) ((value).type == VAL_OBJ)
#define AS_OBJ(value) ((value).as.obj)
#define AS_BOOL(value) ((value).as.boolean)
#define AS_NUMBER(value) ((value).as.number)
#define BOOL_VAL(value) (Value {.type = VAL_BOOL, .as = {.boolean = value}})
#define NIL_VAL (Value {.type = VAL_NIL, .as = {.number = 0}})
#define NUMBER_VAL(value) (Value {.type = VAL_NUMBER, .as = {.number = value}})
#define OBJ_VAL(object) (Value {.type = VAL_OBJ, .as = {.obj = (Obj*)object}})
struct Value {
ValueType type;
union {
bool boolean;
double number;
Obj* obj;
} as;
bool operator==(Value b);
};
struct ValueArray {
int count;
int capacity;
Value* values;
ValueArray();
~ValueArray();
void write(Value value);
};
void printValue(Value value);
void freeValueArray(ValueArray* array);
chunk.h
#pragma once
#include "common.h"
#include "value.h"
typedef enum {
OP_CONSTANT,
OP_NIL,
OP_TRUE,
OP_FALSE,
OP_POP,
OP_GET_LOCAL,
OP_SET_LOCAL,
OP_GET_GLOBAL,
OP_DEFINE_GLOBAL,
OP_SET_GLOBAL,
OP_GET_UPVALUE,
OP_SET_UPVALUE,
OP_EQUAL,
OP_GREATER,
OP_LESS,
OP_NEGATE,
OP_ADD,
OP_SUBTRACT,
OP_MULTIPLY,
OP_DIVIDE,
OP_NOT,
OP_PRINT,
OP_JUMP,
OP_JUMP_IF_FALSE,
OP_LOOP,
OP_CALL,
OP_CLOSURE,
OP_CLOSE_UPVALUE,
OP_RETURN
} OpCode;
struct Chunk {
int count;
int capacity;
uint8_t* code;
int* lines;
ValueArray constants;
Chunk();
~Chunk();
void write(uint8_t byte, int line);
int addConstant(Value value);
};
When compiling these files along with some other files, I got the following error message
Build started...
1>------ Build started: Project: Clox, Configuration: Debug x64 ------
1>chunk.cpp
1>D:\Ankit\Programming\C++\Clox\object.h(45,8): error C3646: 'chunk': unknown override specifier
1>D:\Ankit\Programming\C++\Clox\object.h(45,13): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>D:\Ankit\Programming\C++\Clox\object.h(51,7): error C2143: syntax error: missing ';' before '*'
1>D:\Ankit\Programming\C++\Clox\object.h(51,7): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>D:\Ankit\Programming\C++\Clox\object.h(51,17): error C2238: unexpected token(s) preceding ';'
1>D:\Ankit\Programming\C++\Clox\object.h(61,15): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>D:\Ankit\Programming\C++\Clox\object.h(61,16): error C2065: 'NativeFn': undeclared identifier
1>D:\Ankit\Programming\C++\Clox\object.h(61,24): error C2513: 'int': no variable declared before '='
1>D:\Ankit\Programming\C++\Clox\object.h(61,24): fatal error C1903: unable to recover from previous error(s); stopping compilation
1>INTERNAL COMPILER ERROR in 'C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.30.30705\bin\HostX64\x64\CL.exe'
1> Please choose the Technical Support command on the Visual C++
1> Help menu, or open the Technical Support help file for more information
1>Done building project "Clox.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
I can't understand why these errors are coming out.
You have a cycle in your include files.
object.h => chunk.h => value.h => object.h
So you are getting to a declaration were not all the other types have defined (because #pragma once have prevented the includes happening recursively).
You need to break the cycle by using forward declarations in one of these files and removing a #include.
It's hard to reproduce the problem without all the files. But I think this can be solved with the following change (in value.h)
1: Remove this include:
#pragma once
#include "common.h"
// -> Remove this line #include "object.h"
2: Add a forward declaration:
struct Obj; // Forward declare the class Obj
struct Value {
ValueType type;
union {
bool boolean;
double number;
Obj* obj;
} as;
bool operator==(Value b);
};
The general rule of including from a header file are:
Be judicious, only include what you need.
If you don't need the full type information, forward declare rather than include.
i.e. If you only use a pointer then forward declare the class.
This will probably mean that the source file will need an extra include line but that's OK as you normally don't include source file you don't end up with cycles.
Side-Note there are a couple of other odd things you are doing.
Putting typedef in-front of all your structures.
`typedef struct Value { /* STUFF */} Value;
This is C code and not needed in C++. You can simply do:
`struct Value { /* STUFF */};
and have the same effect.
Don't use macros when normal function's can be used.
// There is no type checking here.
// This is literally text replacement and can go wrong so easily.
#define IS_BOOL(value) ((value).type == VAL_BOOL)
// This is type checked.
// Will more than likely be inclined by the compiler so is
// no more expensive.
inline bool isBool(Value const& value) {return value.type == VA_BOOL;}
Don't use macros when const expression can be used.
#define UINT8_COUNT (UINT8_MAX + 1)
static constexpr std::uint8_t UINT8_COUNT = (UINT8_MAX + 1);
More macro magic that is not correctly type checked:
#define BOOL_VAL(value) (Value {.type = VAL_BOOL, .as = {.boolean = value}})
In this case a proper set of constructors will solve this problem. And you don't need to rely on putting the correct macro in place the compiler will check the types and assign use the correct value.
Don't create your own array types:
struct ValueArray {
int count;
int capacity;
Value* values;
ValueArray();
~ValueArray();
void write(Value value);
};
The standard has some good alternatives already defined and that work very efficiently (std::vector<> or std::array<> and a few others).

How am I supposed to declare this C++ function?

I have a C++ program with an undefined reference error on the call of a method in a class. As near as I can tell, the method is public and I'm calling it with a parameter declared the same as the method definition, but eclipse/gcc tells me it is undefined. I'm not used to C++, can someone please tell me what's wrong with the definition?
The main class:
#include <iostream>
using namespace std;
#include "AttenuationConfigurationTable.h"
int main()
{
flash_entry_struct flash_array[] = { { 10, 20, 30, 40 }, { 50, 60, 70, 80 }, { -1, -1, -1, -1 } };
// note: no undefined reference or any other error for the line with the class
AttenuationConfigurationTable attConfigTable;
// error appears for next line: undefined reference to ...load_attenuation_...
attConfigTable.load_attenuation_calibration_table_from_flash(flash_array);
return 0;
}
The class file:
#include "AttenuationConfigurationTable.h"
#include "flashEntryStruct.h"
AttenuationConfigurationTable::AttenuationConfigurationTable() { }
AttenuationConfigurationTable::~AttenuationConfigurationTable() { }
class Attenuation_configuration_table
{
struct attenuation_voltages_struct
{
float att_value;
float v1;
float v2;
} ;
struct frequency_tables_struct
{
int frequency;
attenuation_voltages_struct attenuation_voltages[100];
int voltages_count = 0;
} ;
frequency_tables_struct _frequency_tables[42];
public:
/************************************************************************/
/* load the table in this object from the given flash memory address */
/************************************************************************/
void load_attenuation_calibration_table_from_flash(flash_entry_struct memory_address[])
{
// bunch of logic here...
}
};
The h file for the class:
#ifndef ATTENUATIONCONFIGURATIONTABLE_H_
#define ATTENUATIONCONFIGURATIONTABLE_H_
#include "flashEntryStruct.h"
class AttenuationConfigurationTable
{
public:
AttenuationConfigurationTable();
virtual ~AttenuationConfigurationTable();
void load_attenuation_calibration_table_from_flash(flash_entry_struct flash_memory_address[]);
};
#endif /* ATTENUATIONCONFIGURATIONTABLE_H_ */
And, just for completeness, the h file defining the parameter structure:
#ifndef FLASHENTRYSTRUCT_H_
#define FLASHENTRYSTRUCT_H_
struct flash_entry_struct
{
uint16_t frequency;
uint16_t scaled_db;
int8_t v1_byte;
int8_t v2_byte;
} ;
#endif /* FLASHENTRYSTRUCT_H_ */
EDIT: the error message itself:
Invoking: Cygwin C++ Linker
g++ -o "HelloCPP.exe" ./src/AttenuationConfigurationTable.o ./src/Hello2.o ./src/HelloCPP.o
/usr/lib/gcc/x86_64-pc-cygwin/10/../../../../x86_64-pc-cygwin/bin/ld: ./src/HelloCPP.o:/cygdrive/c/Users/ralph/files/programming/workspaces/HelloCPP/HelloCPP/Debug/../src/HelloCPP.cpp:15: undefined reference to `AttenuationConfigurationTable::load_attenuation_calibration_table_from_flash(flash_entry_struct*)'
collect2: error: ld returned 1 exit status
make: *** [makefile:58: HelloCPP.exe] Error 1
"make all" terminated with exit code 2. Build might be incomplete.
You declare AttenuationConfigurationTable in the header file with the load_attenuation_calibration_table_from_flash function, but then the function with the same name in the implementation file is inside the definition for another class, Attenuation_configuration_table.
Take the implementation for load_attenuation_calibration_table_from_flash out of the class definition for Attenuation_configuration_table in your cpp file, and define it instead as
void AttenuationConfigurationTable::load_attenuation_calibration_table_from_flash(/* ... */) {
// ...
}
This is the same syntax already used for the constructor and destructor in that file.
In the end, your header should look something like this:
class AttenuationConfigurationTable
{
public:
AttenuationConfigurationTable();
virtual ~AttenuationConfigurationTable();
void load_attenuation_calibration_table_from_flash(flash_entry_struct flash_memory_address[]);
private:
struct attenuation_voltages_struct
{
float att_value;
float v1;
float v2;
} ;
struct frequency_tables_struct
{
int frequency;
attenuation_voltages_struct attenuation_voltages[100];
int voltages_count;
} ;
frequency_tables_struct _frequency_tables[42];
};
and your cpp file should look something like this:
AttenuationConfigurationTable::AttenuationConfigurationTable() { }
AttenuationConfigurationTable::~AttenuationConfigurationTable() { }
void AttenuationConfigurationTable::load_attenuation_calibration_table_from_flash(/* params */) {
// body
}

Structure as init argument in a mex file

I have a mask in simulink that has an init argument field. The init argument in my case is a structure. Now I want to use this structure in the .ccp (to make a mex file).
void init()
{
mxArray *initarg = GetInitArg();
...
}
The GetInitArg() is :
#ifndef GET_INIT_ARG
#define GET_INIT_ARG
mxArray *GetInitArg() {
return rtsys->initArg;
}
#endif
When the initarg is an int, I can call it this way in the void init():
int arg = (int)mxGetPr(initarg)[0];
Now, how would I do if initarg is a Matlab structure?
EDIT
I tried using #remus answer.
My struct look like this :
typedef struct
{
const char *task;
aaa_type aaa;
bbb_type bbb;
ccc_type ccc;
} arg_t;
The struct aaa_type, bbb_type and ccc_type are defined like this :
typedef struct
{
double p1;
double p2;
double p3;
double p4;
double p5;
double p6;
} aaa_type;
I try to get the init arg like this :
void init()
{
mxArray *initarg = GetInitArg();
arg_t arg* = (arg_t*)mxGetPr(initarg);
...
}
But at the arg_t line i'm getting two compilation errors:
error C2143: syntax error : missing ';' before '*'
error C2059: syntax error : '='
The list of MEX functions related to accessing structures is below:
mxGetField
mxSetField
mxGetNumberOfFields
mxGetFieldNameByNumber
mxGetFieldNumber
mxGetFieldByNumber
mxSetFieldByNumber
If you have a 1x1 structure, here's how you'd get one of the values:
mxArray *field_name = mxGetField(initArg, 0, "field_name");
Note that the result is another mxArray. From there you want the usual mxGetPr() for double arrays, or other mxGet... for other datatypes.
See the MEX documentation section on C/C++ Matrix Library for API details on these functions: http://www.mathworks.com/help/matlab/cc-mx-matrix-library.html
If you have the structure definition then you could cast the parameter pointer to it (I haven't tested but it should work since the Matlab structure is a contiguous memory block). Let's say you define your structure somewhere in a .h file:
typedef struct {
double a;
double b;
} mystruct_t;
Then:
mystruct_t *arg = (mystruct_t*)mxGetPr(initarg);
And you can access its members:
if (arg->a == 1) // or whatever

Multiple definition of constant

I have a constant defined in one of the files 1.h :
namespace x {
const int var = 0xff;
}
This file is bundled as a part of a library say 1.a.
Now I include this 1.h in say 2.cpp
#include "1.h"
void func() {
struct t;
t.param_1 = x::var;
}
When i build this in to executable i get the following multiple definition error for the declared constant :
"./../../../include/c++/4.1.2/exception:57: multiple definition of x::var"

C2011: 'struct' type redefinition and C2027: use of undefined type

In a file named types.h, I have defined
struct entry {
entry( int a, int t ) : addr(a), time(t) {}
int addr;
int time;
};
In another file I want to use the struct like this in compress.h:
#include "types.h"
#include <vector>
class Compress {
public:
void insert( int a, int t )
{
theVec.clear();
for (int i = 0; i < 10; ++i)
theVec.push_back( entry(a, t) );
}
private:
std::vector< entry > theVec;
};
In the main file, I wrote
#include "compress.h"
int main()
{
Compress *com = new Compress;
com->insert(10, 100);
return 0;
}
However at the line of push_back, I get these errors
error C2011: 'entry' : 'struct' type redefinition
see declaration of 'entry'
error C2027: use of undefined type 'entry'
see declaration of 'entry'
How can I fix that?
In your types.h file you should have something like this:
#ifndef TYPES_H
#define TYPES_H
struct ...
#endif
This will prevent the compiler from parsing the include file mulitple times if you include it more than once, which would cause multiple definitions.
The name itself doesn't matter, but you should make sure that it is unique and not defined by some other include file as well.
You may want to check the include guard of types.h.
Try to have the file start with the line
#pragma once
// your declarations