Could sqlite3 generate non-deterministic errors? - c++

I am getting random errors when saving and reading data in Sqlite3 database (VS 2015 Express test).
Made simple trace and can see there is something a bit modified read by select after update sometimes, but not sure where it comes from or what is reason.
Sometimes they are frequent, but now they are very rare - last time 2 times different uint8_t values during few manual runs of same testcase in a short time for example...
How can I check what is causing this - DB / FS / sqlite3.c problem or something else ?
I am testing on a 3 month old NTB having single SSD drive only.
My tracing code:
sqlite3_trace_v2(database, SQLITE_TRACE_STMT | SQLITE_TRACE_ROW, DBtrace::Trace, 0);
class DBtrace {
public:
static bool logNow;
static std::string log;
DBtrace(bool enable = false) { logNow = enable; }
DBtrace & DBtrace::Instance()
{
static DBtrace instance;
return instance;
}
static int Trace(unsigned int d, void *m, void *p, void *x);
};
#include "sqlite3.h"
#include "db_trace.hpp"
#include <stdio.h>
#include <algorithm>
using namespace std;
namespace databaseNS
{
bool DBtrace::logNow;
std::string DBtrace::log;
static int isUseless(int c) { return c < 32; }
bool BothAreSpaces(char lhs, char rhs) { return (lhs == rhs) && (lhs < 32); }
int DBtrace::Trace(unsigned int d, void *m, void *p, void *x) {
if (!logNow) return 0;
string sql;
std::string::iterator new_end;
sqlite3_value *v;
sqlite3_stmt *pStmt = reinterpret_cast<sqlite3_stmt *>(p);
int cc = sqlite3_column_count(pStmt);
switch (d)
{
case SQLITE_TRACE_STMT:
sql = sqlite3_expanded_sql(pStmt);
new_end = std::unique(sql.begin(), sql.end(), BothAreSpaces);
sql.erase(new_end, sql.end());
sql += "\r\n";
log += sql;
break;
case SQLITE_TRACE_ROW:
int n = sqlite3_bind_parameter_count(pStmt);
for (int i = 0; i < cc; i++)
{
sql = sqlite3_column_name(pStmt, i);
v = sqlite3_column_value(pStmt, i);
if (v->flags & MEM_Int) {
sql += ":" + std::to_string(v->u.i) + ", ";
log += sql;
}
if (v->flags & MEM_Str) {
sql += ":";
sql += v->z;
sql += ", ";
log += sql;
};
}
log += "\r\n";
break;
}
return 0;
}
}
And a lot of required declarations found in sqlite3.c (db_trace.hpp)
#include <string>
/**
* #brief Routine for preparation sql queries needed for data handling
*
* #return true if success, false otherwise
*
*/
/*
** Integers of known sizes. These typedefs might change for architectures
** where the sizes very. Preprocessor macros are available so that the
** types can be conveniently redefined at compile-type. Like this:
**
** cc '-DUINTPTR_TYPE=long long int' ...
*/
#ifndef UINT32_TYPE
# ifdef HAVE_UINT32_T
# define UINT32_TYPE uint32_t
# else
# define UINT32_TYPE unsigned int
# endif
#endif
#ifndef UINT16_TYPE
# ifdef HAVE_UINT16_T
# define UINT16_TYPE uint16_t
# else
# define UINT16_TYPE unsigned short int
# endif
#endif
#ifndef INT16_TYPE
# ifdef HAVE_INT16_T
# define INT16_TYPE int16_t
# else
# define INT16_TYPE short int
# endif
#endif
#ifndef UINT8_TYPE
# ifdef HAVE_UINT8_T
# define UINT8_TYPE uint8_t
# else
# define UINT8_TYPE unsigned char
# endif
#endif
#ifndef INT8_TYPE
# ifdef HAVE_INT8_T
# define INT8_TYPE int8_t
# else
# define INT8_TYPE signed char
# endif
#endif
#ifndef LONGDOUBLE_TYPE
# define LONGDOUBLE_TYPE long double
#endif
typedef sqlite_int64 i64; /* 8-byte signed integer */
typedef sqlite_uint64 u64; /* 8-byte unsigned integer */
typedef UINT32_TYPE u32; /* 4-byte unsigned integer */
typedef UINT16_TYPE u16; /* 2-byte unsigned integer */
typedef INT16_TYPE i16; /* 2-byte signed integer */
typedef UINT8_TYPE u8; /* 1-byte unsigned integer */
typedef INT8_TYPE i8; /* 1-byte signed integer */
typedef struct FuncDef FuncDef;
struct sqlite3_value {
union MemValue {
double r; /* Real value used when MEM_Real is set in flags */
i64 i; /* Integer value used when MEM_Int is set in flags */
int nZero; /* Extra zero bytes when MEM_Zero and MEM_Blob set */
const char *zPType; /* Pointer type when MEM_Term|MEM_Subtype|MEM_Null */
FuncDef *pDef; /* Used only when flags==MEM_Agg */
} u;
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
u8 enc; /* SQLITE_UTF8, SQLITE_UTF16BE, SQLITE_UTF16LE */
u8 eSubtype; /* Subtype for this value */
int n; /* Number of characters in string value, excluding '\0' */
char *z; /* String or BLOB value */
/* ShallowCopy only needs to copy the information above */
char *zMalloc; /* Space to hold MEM_Str or MEM_Blob if szMalloc>0 */
int szMalloc; /* Size of the zMalloc allocation */
u32 uTemp; /* Transient storage for serial_type in OP_MakeRecord */
sqlite3 *db; /* The associated database connection */
void(*xDel)(void*);/* Destructor for Mem.z - only valid if MEM_Dyn */
#ifdef SQLITE_DEBUG
Mem *pScopyFrom; /* This Mem is a shallow copy of pScopyFrom */
u16 mScopyFlags; /* flags value immediately after the shallow copy */
#endif
};
/* One or more of the following flags are set to indicate the validOK
** representations of the value stored in the Mem struct.
**
** If the MEM_Null flag is set, then the value is an SQL NULL value.
** For a pointer type created using sqlite3_bind_pointer() or
** sqlite3_result_pointer() the MEM_Term and MEM_Subtype flags are also set.
**
** If the MEM_Str flag is set then Mem.z points at a string representation.
** Usually this is encoded in the same unicode encoding as the main
** database (see below for exceptions). If the MEM_Term flag is also
** set, then the string is nul terminated. The MEM_Int and MEM_Real
** flags may coexist with the MEM_Str flag.
*/
#define MEM_Null 0x0001 /* Value is NULL (or a pointer) */
#define MEM_Str 0x0002 /* Value is a string */
#define MEM_Int 0x0004 /* Value is an integer */
#define MEM_Real 0x0008 /* Value is a real number */
#define MEM_Blob 0x0010 /* Value is a BLOB */
#define MEM_AffMask 0x001f /* Mask of affinity bits */
/* Available 0x0020 */
/* Available 0x0040 */
#define MEM_Undefined 0x0080 /* Value is undefined */
#define MEM_Cleared 0x0100 /* NULL set by OP_Null, not from data */
#define MEM_TypeMask 0xc1ff /* Mask of type bits */

Related

G711Codec.h:44:1: error build: unknown type name 'class'; did you mean 'Class'?

want to add some Camera SDK in my swift project.. but cant solve this error..
libAndHeaders/MediaPlayer/G711Codec.h:42:1: error build: unknown type name 'class'; did you mean 'Class'?
maybe this is cpp header file or some other file. when i include this in my Objectice-c header file then it gives me this err..
/*
G711解码库
*/
#ifndef _G711_CODEC_H_
#define _G711_CODEC_H_
#define word16 short
#define word32 int
#define Word16 short
#define Word32 int
#define HI_VOICE_MAX_FRAME_SIZE (480+1) /* dont change it */
#define BIAS (0x84) /* Bias for linear code. */
#define CLIP 8159
#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */
#define QUANT_MASK (0xf) /* Quantization field mask. */
#define NSEGS (8) /* Number of A-law segments. */
#define SEG_SHIFT (4) /* Left shift for segment number. */
#define SEG_MASK (0x70) /* Segment field mask. */
static int seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF,
0x1FF, 0x3FF, 0x7FF, 0xFFF};
static int seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF,
0x3FF, 0x7FF, 0xFFF, 0x1FFF};
/* HISI_VOICE codec type */
/* Real-time transport protocol(RTP) */
#define G711_A 0x01 /* 64kbps G.711 A, see RFC3551.txt 4.5.14 PCMA */
#define G711_U 0x02 /* 64kbps G.711 U, see RFC3551.txt 4.5.14 PCMU */
#define G711_ORG_A 0x41 /* original version 64kbps G.711 A */
#define G711_ORG_U 0x42 /* original version 64kbps G.711 U */
typedef int (*G711_Decoder)(int sample);
class G711Codec
{
check this screenshot
Yes, it´s a c++ header. You can mix obj-c and c++ if you need to (such source files need to have .mm extension, so that the compiler recognizes them), but probably you can choose another (obj-c) framework for what you need.

C++ Linker error undefined reference [duplicate]

This question already has answers here:
Combining C++ and C - how does #ifdef __cplusplus work?
(4 answers)
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 4 years ago.
I have been working with C on the embedded side and C# on PC side for quite some time. Now I decided to start working with C++ on an embedded target.
However the linker tells me that it could not find my function.
The complete error looks like this:
Building target: Cpp_Test.elf
Invoking: MCU G++ Linker
arm-none-eabi-g++ -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -specs=nosys.specs -specs=nano.specs -T"../STM32F429ZITx_FLASH.ld" -Wl,-Map=output.map -Wl,--gc-sections -fno-exceptions -fno-rtti -o "Cpp_Test.elf" #"objects.list" -lm
Src/freertos.o: In function `StartDefaultTask':
\Cpp_Test\Debug/../Src/freertos.c:127: undefined reference to `calc_values'
The test_cplus.h file looks like this:
#include "stdint.h"
int calc_values();
The test_cplus.cpp file looks like this:
#include "test_cplus.h"
#include <iostream>
using namespace std;
class Rectangle {
int width, height;
public:
void set_values (int,int);
int area() {return width*height;}
};
void Rectangle::set_values (int x, int y) {
width = x;
height = y;
}
int calc_values()
{
Rectangle rect;
rect.set_values(1,2);
int area = rect.area();
return area;
}
Could you point me in the right direction?
Edit freertos.c
/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "cmsis_os.h"
/* USER CODE BEGIN Includes */
#include "test_file.h"
#include "test_cplus.h"
/* USER CODE END Includes */
/* Variables -----------------------------------------------------------------*/
osThreadId defaultTaskHandle;
/* USER CODE BEGIN Variables */
/* USER CODE END Variables */
/* Function prototypes -------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
void StartDefaultTask(void const * argument);
extern void MX_USB_DEVICE_Init(void);
extern void MX_FATFS_Init(void);
void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
#ifdef __cplusplus
}
#endif
/* USER CODE BEGIN FunctionPrototypes */
/* USER CODE END FunctionPrototypes */
/* Hook prototypes */
/* Init FreeRTOS */
void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
/* start timers, add new ones, ... */
/* USER CODE END RTOS_TIMERS */
/* Create the thread(s) */
/* definition and creation of defaultTask */
osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);
defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
/* USER CODE END RTOS_THREADS */
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
/* USER CODE END RTOS_QUEUES */
}
/* StartDefaultTask function */
void StartDefaultTask(void const * argument)
{
/* init code for USB_DEVICE */
MX_USB_DEVICE_Init();
/* init code for FATFS */
MX_FATFS_Init();
/* USER CODE BEGIN StartDefaultTask */
/* Infinite loop */
for(;;)
{
run_test();
calc_values();
osDelay(100);
}
/* USER CODE END StartDefaultTask */
}
/* USER CODE BEGIN Application */
/* USER CODE END Application */

Interfaces in C++-Header File

Im supposed to write a C++-programm that interacts with a uEye camera.
For this I have to include several files, one of them being a header file that has around 30 interfaces in it that are like the one shown below.
When I run a c++ programm including this header file, Im getting the error:
"error: expected identifier or '(' before ':' token"
at the first line (interface IuEyeAutoFeatures : public IUnknown) of every single interface in the header file.
Heres one of the interfaces from the header file:
interface IuEyeAutoFeatures : public IUnknown
{
STDMETHOD(SetAutoBrightnessReference)(long lReference) = 0;
STDMETHOD(GetAutoBrightnessReference)(long* plReference) = 0;
STDMETHOD(SetAutoBrightnessMaxExposure)(long lMaxExposure) = 0;
STDMETHOD(GetAutoBrightnessMaxExposure)(long* plMaxExposure) = 0;
STDMETHOD(SetAutoBrightnessMaxGain)(long lMaxGain) = 0;
STDMETHOD(GetAutoBrightnessMaxGain)(long* plMaxGain) = 0;
STDMETHOD(SetAutoBrightnessSpeed)(long lSpeed) = 0;
STDMETHOD(GetAutoBrightnessSpeed)(long* plSpeed) = 0;
STDMETHOD(SetAutoBrightnessAOI)(long lXPos, long lYPos, long lWidth, long lHeight) = 0;
STDMETHOD(GetAutoBrightnessAOI)(long* plXPos, long* plYPos, long* plWidth, long* plHeight) = 0;
STDMETHOD(SetAutoWBGainOffsets)(long lRedOffset, long lBlueOffset) = 0;
STDMETHOD(GetAutoWBGainOffsets)(long* plRedOffset, long* plBlueOffset) = 0;
STDMETHOD(SetAutoWBGainRange)(long lMinRGBGain, long lMaxRGBGain) = 0;
STDMETHOD(GetAutoWBGainRange)(long* plMinRGBGain, long* plMaxRGBGain) = 0;
STDMETHOD(SetAutoWBSpeed)(long lSpeed) = 0;
STDMETHOD(GetAutoWBSpeed)(long* plSpeed) = 0;
STDMETHOD(SetAutoWBAOI)(long lXPos, long lYPos, long lWidth, long lHeight) = 0;
STDMETHOD(GetAutoWBAOI)(long* plXPos, long* plYPos, long* plWidth, long* plHeight) = 0;
};
DEFINE_GUID(IID_IuEyeFaceDetection,
0xe122a994, 0xfc4d, 0x445b, 0xb2, 0x1c, 0x30, 0x8b, 0x67, 0x48, 0x44, 0xe0);
#ifndef DS_EXPORT
# define DS_EXPORT
# ifdef _UEYETIME
# undef _UEYETIME
# endif
# ifdef UEYETIME
# undef UEYETIME
# endif
typedef struct _UEYETIME
{
WORD wYear;
WORD wMonth;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
BYTE byReserved[10];
} UEYETIME;
#endif /* DS_EXPORT */
#ifndef DS_EXPORT
# define DS_EXPORT
# ifdef S_FDT_INFO_EL
# undef S_FDT_INFO_EL
# endif
# ifdef FDT_INFO_EL
# undef FDT_INFO_EL
# endif
/*!
* \brief uEye face detection info element data type.
* Info on a single detected face as listed by \see FDT_INFO_LIST.
*/
typedef struct S_FDT_INFO_EL
{
INT nFacePosX; /*!< \brief Start X position. */
INT nFacePosY; /*!< \brief Start Y position. */
INT nFaceWidth; /*!< \brief Face width. */
INT nFaceHeight; /*!< \brief Face height. */
INT nAngle; /*!< \brief Face Angle (0...360° clockwise, 0° at twelve o'clock position. -1: undefined ). */
UINT nPosture; /*!< \brief Face posture. */
UEYETIME TimestampSystem; /*!< \brief System time stamp (device query time) . */
UINT64 nReserved; /*!< \brief Reserved for future use. */
UINT nReserved2[4]; /*!< \brief Reserved for future use. */
} FDT_INFO_EL;
#endif /* DS_EXPORT */
#ifndef DS_EXPORT
# define DS_EXPORT
# ifdef S_FDT_INFO_LIST
# undef S_FDT_INFO_LIST
# endif
# ifdef FDT_INFO_LIST
# undef FDT_INFO_LIST
# endif
/*!
* \brief uEye face detection info list data type.
* List of detected faces, lists \see FDT_INFO_EL objects.
*/
typedef struct S_FDT_INFO_LIST
{
UINT nSizeOfListEntry; /*!< \brief Size of one list entry in byte(in). */
UINT nNumDetectedFaces; /*!< \brief Number of detected faces(out). */
UINT nNumListElements; /*!< \brief Number of list elements(in). */
UINT nReserved[4]; /*!< \brief reserved for future use(out). */
FDT_INFO_EL FaceEntry[1]; /*!< \brief First face entry. */
} FDT_INFO_LIST;
#endif /* DS_EXPORT */
As far as I know, declaring interfaces using the word "interface" is done in languages like Java but not in c++, so I dont understand why this header file declares interfaces like this. Since this header file is provided by the company IDS after downloading their driver it should be correct i suppose.
How can I fix that bug and make my program work?
Thanks in advance
interface is a preprocessor macro, commonly used with COM interfaces. It is defined in combaseapi.h as:
#define __STRUCT__ struct
#define interface __STRUCT__
You need to include that header file (either directly or indirectly through #include <objbase.h>) before including the interface header.

Multiple classes in multiple files - C++ / Arduino

I have to code a the library motorIR, which uses NECIRrcv to extract the IR code from a sensor.
Initially I tried doing it using two libraries, but that doesn't seem to be easy as I read, so I decide to include both the header and the source file of NECIRrcv in my Arduino library motorIR.
I'm having some trouble with defining NECIRrcv sensor in motorIR.
If I do it where it's placed in the code, no signal is available (while(sensor.available())is never entered).
I can understand that's logical, since it redefines sensor every time I call motorIR::control().
My real problem is that I have no clue of where I should declare sensor, the object of NECIRrcv class, in motorIR.
I did a little research about it, and since I haven't worked with extern classes before, I've ended up even more confused about if using one it's necessary.
I'd be very grateful if someone can invest a few minutes helping me with this subject. Hope you can understand my explanations.
Here you are the different files:
File motorIR.h
#ifndef motorIR_h
#define motorIR_h
#include "Arduino.h"
#include "NECIRrcv.h"
#define STANDBY 999
#define inputIR 2
#define PWM_1 3
#define MI_1 4
#define MD_1 5
#define PWM_2 6
#define MI_2 7
#define MD_2 8
#define FORWARD
#define BACKWARD
class motorIR
{
public: // Funciones públicas
motorIR(int pPWM_1, int pMI_1, int pMD_1, int pPWM_2, int pMI_2, int pMD_2);
void setMotor(int PWM, int MI, int MD);
void begin();
void control();
void translate();
void serialPrint();
private: // Variables privadas
int _PWM= STANDBY;
int _MI;
int _MD;
unsigned long _IRcode;
// static NECIRrcv & getSensor() // <--- getSensor() added
// {
// static NECIRrcv sensor(4);
// return sensor;
// }
// static NECIRrcv & getSensor()
// {
// static NECIRrcv sensor(4);
// static bool firstRun(true);
// if ( firstRun )
// {
// sensor.begin();
// firstRun = false;
// }
// return sensor;
// }
};
#endif
File motorIR.cpp
#include "Arduino.h"
#include "motorIR.h"
#include <string.h>
motorIR::motorIR(int PWM, int MI, int MD) // Constructor
{
_MI= MI +A0;
_PWM= PWM +A0;
_MD= MD +A0;
}
void motorIR::beginner()
{
Serial.begin(9600);
Serial.print("Begin");
}
void motorIR::control(int i)
{
NECIRrcv sensor(4) ; // I doesn't work as expected if placed here
sensor.begin();
Serial.println("Checkpoint");
while (sensor.available())
{
Serial.print("Detection");
IRcode= sensor.read();
Serial.print(IRcode, DEC);
Serial.print(IRcode, HEX);
Serial.print(IRcode, BIN);
}
}
File NECIRrcv.h (given)
#ifndef NECIRrcv_h
#define NECIRrcv_h
#include <Arduino.h>
#include "motorIR.h"
#define USECPERTICK 50 // microseconds per clock interrupt tick
#define CLKFUDGE 5 // fudge factor for clock interrupt overhead
#define CLKMAX 256 // max value for clock (timer 2)
#define PRESCALE 8 // timer2 clock prescale
#define SYSCLOCK 16000000 // main Arduino clock
#define CLKSPERUSEC (SYSCLOCK/PRESCALE/1000000) // timer clocks per microsecond
#define MAXBUF 8 // IR command code buffer length (circular buffer)
// IR detector output is active low
#define MARK 0
#define SPACE 1
#define NBITS 32 // bits in IR code
#define BLINKLED 13
// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
// clock timer reset value
#define INIT_TIMER_COUNT2 (CLKMAX - USECPERTICK*CLKSPERUSEC + CLKFUDGE)
#define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT2
// pulse parameters -- nominal usec
#define STARTNOM 9000
#define SPACENOM 4500
#define BITMARKNOM 620
#define ONESPACENOM 1600
#define ZEROSPACENOM 480
#define RPTSPACENOM 2180
#define TOLERANCE 20 // percent
#define LTOL (1.0 - TOLERANCE/100.)
#define UTOL (1.0 + TOLERANCE/100.)
// pulse parameters (tick counts)
#define STARTMIN (int)((STARTNOM/USECPERTICK)*LTOL) // start MARK
#define STARTMAX (int)((STARTNOM/USECPERTICK)*UTOL)
#define SPACEMIN (int)((SPACENOM/USECPERTICK)*LTOL)
#define SPACEMAX (int)((SPACENOM/USECPERTICK)*UTOL)
#define BITMARKMIN (int)((BITMARKNOM/USECPERTICK)*LTOL-2) // extra tolerance for low counts
#define BITMARKMAX (int)((BITMARKNOM/USECPERTICK)*UTOL+2)
#define ONESPACEMIN (int)((ONESPACENOM/USECPERTICK)*LTOL)
#define ONESPACEMAX (int)((ONESPACENOM/USECPERTICK)*UTOL)
#define ZEROSPACEMIN (int)((ZEROSPACENOM/USECPERTICK)*LTOL-2)
#define ZEROSPACEMAX (int)((ZEROSPACENOM/USECPERTICK)*UTOL+2)
#define RPTSPACEMIN (int)((RPTSPACENOM/USECPERTICK)*LTOL)
#define RPTSPACEMAX (int)((RPTSPACENOM/USECPERTICK)*UTOL)
// receiver states
#define IDLE 1
#define STARTH 2
#define STARTL 3
#define BIT 4
#define ONE 5
#define ZERO 6
#define STOP 7
#define BITMARK 8
#define RPTMARK 9
// macros
#define GETIR(X) ((byte)digitalRead(X)) // used to read IR pin
#define nextstate(X) (irparams.rcvstate = X)
// state machine variables irparams
static volatile struct {
byte rcvstate ; // IR receiver state
byte bitcounter ; // bit counter
byte irdata ; // MARK or SPACE read from IR input pin
byte fptr ; // irbuf front pointer
byte rptr ; // irbuf rear pointer
byte irpin ; // pin for IR data from detector
byte blinkflag ; // TRUE to enable blinking of pin 13 on IR processing
unsigned int timer ; // state timer
unsigned long irmask ; // one-bit mask for constructing IR code
unsigned long ircode ; // IR code
unsigned long irbuf[MAXBUF] ; // circular buffer for IR codes
} irparams ;
// main class
class NECIRrcv
{
public:
NECIRrcv(int irpin);
unsigned long read();
void begin();
int available() ;
void flush() ;
void blink13(int blinkflag) ;
private:
} ;
extern NECIRrcv sensor; // <-------- declaring object as extern
#endif
File NECIRrcv.cpp (given)
#include <Arduino.h>
#include "NECIRrcv.h"
#include "motorIR.h"
NECIRrcv::NECIRrcv(int irpin)
{
irparams.irpin = irpin ;
}
void NECIRrcv::begin() {
//(...)
}
unsigned long NECIRrcv::read()
{
unsigned long ircode ;
//(...)
return((unsigned long)-1) ;
}
// (...)
Eduardo
If you need only a sensor for all instances of motorIR, I suppose that it could be a static member of the class.
Or a static variable in a static method; like this
class motorIR
{
public: // Funciones públicas
motorIR(int PWM, int MI, int MD);
void beginner();
void control(int i);
private: // Variables privadas
int _PWM= STANDBY;
int _MI;
int _MD;
int pin_IR;
unsigned long IRcode;
static NECIRrcv & getSensor() // <--- getSensor() added
{ static NECIRrsv sensor(4); return sensor; }
};
You can use it in this way
void motorIR::control(int i)
{
// NECIRrcv sensor(4) ; no more here
getSensor().begin();
Serial.println("Checkpoint");
while (getSensor().available())
{
Serial.print("Detection");
IRcode= getSensor().read();
Serial.print(IRcode, DEC);
Serial.print(IRcode, HEX);
Serial.print(IRcode, BIN);
}
}
p.s.: caution: not tested
p.s.2: sorry for my bad English
--- EDIT ---
The error is "'NECIRrcv' does not name a type" or "'NECIRrcs' does not name a type"?
In my example I've written, by mistake "NECIRrcs" instead of "NECIRrcv"; sorry.
About your need to begin() only one time the sensor, you can modify the getSensor() method in this way
static NECIRrcv & getSensor()
{
static NECIRrsv sensor(4);
static bool firstRun(true);
if ( firstRun )
{
sensor.begin();
firstRun = false;
}
return sensor;
}
Caution: not tested.
I loved the idea of declaring the object NECIRrcv::sensor as part of class motorIR though, but trying to define NECIRrcv sensor(4) anywhere in motorIR.h leads to error: 'NECIRrcv' does not name a type; so it would be interesting to solve this problem in order to be able to implement #max66 's idea (or eve just to figure out why motorIR.h doesn't recognize NECIRrcv properly).
In spite of that, I think I've run into an alternative solution: using an extern object (as it's described here).
It can be implemented as it follows:
In NECIRrcv header:
#ifndef NECIRrcv_h
#define NECIRrcv_h
#include <Arduino.h>
// (...)
class NECIRrcv
{
public:
NECIRrcv(int irpin);
// (...)
private:
} ;
extern NECIRrcv sensor; // <-------- declaring object as extern
#endif
In motorIR source file:
#include "Arduino.h"
#include "motorIR.h"
#include <string.h>
NECIRrcv sensor(4); // <--------- defining object
motorIR::motorIR(int PWM, int MI, int MD)
{
_MI= MI +A0;
_PWM= PWM +A0;
_MD= MD +A0;
}
void motorIR::beginner()
{
Serial.begin(9600);
Serial.print("Begin");
sensor.begin(); // <-------- now I can initialize sensor here
}
void motorIR::control(int i)
{
// NECIRrcv sensor(4) ;
// sensor.begin();
Serial.println("Checkpoint");
while (sensor.available()) // <-- method 1
{
Serial.print("Detection");
IRcode= sensor.read(); // <-- method 2
Serial.print(IRcode, DEC);
Serial.print(IRcode, HEX);
Serial.print(IRcode, BIN);
}
}

Undefined reference when a function is listed in a header file, but fine if I copy and paste code directly

I am working on a large project in C++ that is proprietary, so I can't actually share the source code. I have most of the code compiled, but there is one function, in a particular file, that is giving me quite a bit of trouble.
I've created a simple example that shows what the problem is. We have:
WTPSHORT.H
#ifndef WTP_H
#define WTP_H 1
#define VERSION "Version 2.1"
#define DATE "Nov., 2001"
/* ANSI C header files */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <fcntl.h>
#include <ctype.h>
#define TRUE 1
#define FALSE 0
/************ Data structures for Water Treatment Plant ***************/
struct Effluent { /****** Data Packet for All Unit Processes *******/
/* Operating data: */
double DegK; /* Temperature (Deg K) */
double Flow; /* Average flow (MGD) */
double Peak; /* Max hourly flow (MDG) */
/* Unit process counters: */
short cl2cnt; /* Number of times chlorine added. */
/* Measurable Water Quality Parameters: */
double pH; /* [H+]=pow(10,-pH) (-) */
/* More variable definitions go here */
double beta_br; /* Constant for chlorine to bromine reactivity ratio */
double time_step; /* Time step (hrs) */
}; /************ End of struct Effluent ************/
/*****************************************/
struct ProcessTrain { /* Control Structure for Process Train */
struct UnitProcess *head; /* First UnitProcess in ProcessTrain */
struct UnitProcess *null; /* Always NULL */
struct UnitProcess *tail; /* Last UnitProcess in ProcessTrain */
char file_name[120]; /* Full path and extension */
}; /*****************************************/
struct UnitProcess { /********** Treatment Process ***************/
struct UnitProcess *next; /* Double Linked list */
struct UnitProcess *prev; /* " " " */
short type; /* Defined unit process types */
short pad; /* Maintain 32 bit alinment of pointers */
union { /* Design and operating parameters: */
void *ptr;
struct Influent *influent;
struct Mechdbp *mechdbp; //FOR MECH MODEL
struct Alum *alum;
struct Gac *gac;
struct Filter *filter;
struct Basin *basin;
// struct Membrane *membrane;
struct Mfuf *mfuf;
struct Nf *nf;
struct Iron *iron;
struct chemical *chemical;
struct clo2 *clo2;
struct lime *lime;
/*struct WTP_effluent *wtp_effluent; No longer needed - WJS, 11/98 */
struct Avg_tap *avg_tap;
struct End_of_system *end_of_system;
} data;
struct Effluent eff;
};
struct Influent { /* Raw Water Data */
double pH; /* (-) */
double temp; /* Average temperature (C) */
double low_temp; /* Low temperature for disinfection (C) */
double toc; /* (mg/L) */
double uv254; /* (1/cm) */
double bromide; /* (mg/L) */
double alkalinity; /* (mg/L as CaCO3) */
double calcium; /* Calcium Hardness (mg/L as CaCO3) */
double hardness; /* Total Hardness (mg/L as CaCO3) */
double nh3; /* Ammonia (mg/L as N) */
double ntu; /* Turbidity */
double crypto_req; /* Crypto Log removal + Log Inact. required*/
double clo2_crypto_ct_mult; /* Multiplier */
double peak_flow; /* Peak Hourly Flow for disinfection (MGD) */
double avg_flow; /* Average Flow (MGD) */
int swflag; /* TRUE=Surface Water; FALSE=Ground Water */
// char *run_name;
};
void s1_s2_est(struct UnitProcess *unit);
/* define(s) for UnitProcess.type */
#define VACANT 0
#define INFLUENT 1
#define RAPID_MIX 2
#define SLOW_MIX 3
#define SETTLING_BASIN 4
#define FILTER 5
#define BASIN 6
#define CONTACT_TANK 7
#define CLEARWELL 8
#define O3_CONTACTOR 9
#define GAC 10
#define MFUF_UP 11
#define NF_UP 12
#endif
And then there are two source files in the project:
s1s2_est.c
/* s1s2_est.c -- December, 2000*/
#include "WTPSHORT.H"
void s1_s2_est(struct UnitProcess *unit)
{
double toc, uva, s1_0, s2h_0, s2star_0, s2t_0, s1_f, s2h_f, s2star_f, s2t_f, H;
struct Effluent *eff;
eff = &unit->eff;
/* Get these inputs */
toc = eff->TOC;
uva = eff->UV;
s1_0 = eff->s1;
s2h_0 = eff->s2h;
s2star_0 = eff->s2_star;
H = pow(10.0, -eff->pH);
s2t_0 = s2h_0 + s2star_0;
s1_f = s1_0;
s2t_f = s2t_0;
s2star_f = s2star_0;
s2h_f = s2h_0;
if(eff->s1_s2_estflag == 'C')
{
/* Safety check */
if (toc < 0.0) toc = 0.0;
if (uva < 0.0) uva = 0.0;
s1_f = 5.05 * pow(toc, 0.57) * pow(uva, 0.54);
s2t_f = 13.1 * pow(toc, 0.38) * pow(uva, 0.40);
/* No increases in the S values allowed */
if(s1_f > s1_0 ) s1_f = s1_0;
if(s2t_f > s2t_0) s2t_f = s2t_0;
/* Speciate S2 */
s2h_f = s2t_f * eff->k21r * H / (eff->k21f + eff->k21r * H);
s2star_f = s2t_f * eff->k21f / (eff->k21f + eff->k21r * H);
}
if(eff->s1_s2_estflag != 'C' && unit->type == INFLUENT)
{/* Speciate S2 in raw water*/
s2h_f = s2t_f * eff->k21r * H / (eff->k21f + eff->k21r * H);
s2star_f = s2t_f * eff->k21f / (eff->k21f + eff->k21r * H);
}
/* Update Effluent data structure */
eff->s1 = s1_f;
eff->s2h = s2h_f;
eff->s2_star = s2star_f;
}/* End subroutine "s1_s2_est()"*/
and then
main.cpp
#include <stdio.h>
#include "WTPSHORT.H"
int main(int argc, char **argv)
{
UnitProcess *myunit;
s1_s2_est(myunit);
printf("done\n");
return 0;
}
When compiling and linking I see this error:
C:\WINDOWS\system32\cmd.exe /C "C:/MinGW/bin/mingw32-make.exe -j8 SHELL=cmd.exe -e -f Makefile"
"----------Building project:[ simple - Debug ]----------"
mingw32-make.exe[1]: Entering directory 'C:/Users/joka0958/Desktop/wtp/compiledwtp/simple'
C:/MinGW/bin/g++.exe -c "C:/Users/joka0958/Desktop/wtp/compiledwtp/simple/main.cpp" -g -O0 -Wall -o ./Debug/main.cpp.o -I. -I.
C:/MinGW/bin/gcc.exe -c "C:/Users/joka0958/Desktop/wtp/compiledwtp/simple/s1s2_est.c" -g -O0 -Wall -o ./Debug/s1s2_est.c.o -I. -I.
C:/Users/joka0958/Desktop/wtp/compiledwtp/simple/main.cpp: In function 'int main(int, char**)':
C:/Users/joka0958/Desktop/wtp/compiledwtp/simple/main.cpp:7:22: warning: 'myunit' is used uninitialized in this function [-Wuninitialized]
s1_s2_est(myunit);
^
C:/MinGW/bin/g++.exe -o ./Debug/simple #"simple.txt" -L.
./Debug/main.cpp.o: In function `main':
C:/Users/joka0958/Desktop/wtp/compiledwtp/simple/main.cpp:7: undefined reference to `s1_s2_est(UnitProcess*)'
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe[1]: [Debug/simple] Error 1
mingw32-make.exe: [All] Error 2
simple.mk:78: recipe for target 'Debug/simple' failed
mingw32-make.exe[1]: Leaving directory 'C:/Users/joka0958/Desktop/wtp/compiledwtp/simple'
Makefile:4: recipe for target 'All' failed
2 errors, 1 warnings
So the question is: Why am I getting an undefined reference?
I realize this is one of those errors that probably masks another problem, but I have really exhausted all possibilities, in my mind, of what could be causing the problem. Note that this is part of a larger project where many other functions compile and link properly.
By the way I am using Codelite with the MinGW compiler on Windows 10.
I'm sorry for all the consternation this question caused. It turns out that there was C++-specific functions within this file, but because the file was named with a *.c, codelite defaulted to the C compiler to actually compile this particular source file. Once I changed the filename, the code compiled successfully. Thanks for all of your useful suggestions!