Error 28: Expression must have a constant value - c++

I have a section of c++ code in keil uvision5 that is getting error 28: expression must have a constant value. I am trying to figure out how to fix it.
this is the line (inside of a function) that it is happening on:
osPoolDef_t pool_def = { queue_def->queue_sz, queue_def->item_sz};
it does not like the variables queue_sz or item_sz.
here is the definition of osPoolDef_t:
typedef const struct os_pool_def {
uint32_t pool_sz; /* number of items (elements) in the pool */
uint32_t item_sz; /* size of an item */
void *pool; /* pointer to memory for pool */
} osPoolDef_t;
and queue_def is a pointer to osMailQDef_t shown below:
typedef const struct os_mailQ_def {
uint32_t queue_sz; /* number of elements in the queue */
uint32_t item_sz; /* size of an item */
struct os_mailQ_cb **cb;
} osMailQDef_t;
hopefully that is enough information.
It seems that the problem is that I am not using c99 anymore, but the code worked fine for that file when I used c99. Is there a way to force the compilation of just that file to be done with c99?

You can force the armcc compiler to use C99 with the --c99 option.

Related

How to use RHVoice Text To Speech C/C++ library

I'm using rhvoice library in a qt c++ project, and I'm struggling to make it work and speak.
So far i have managed to load voices and voice profiles to a tts_engine, but no sound plays even tho the speak function gives no error.
So I'm wondering if someone could give me an example on how to initialize a tts engine and use it to speak strings, or any help on how to use this library, because the documentation wasn't enough for me to figure it out.
One thing i noticed is that RHVoice_callbacks causes my application to crash even if i just initialize it without using it.
Code:
The function that will implement the library:
short samples[]={140,139,145};
//initialize callbacks
/*RHVoice_callbacks *callbacks;
callbacks->set_sample_rate(24000,NULL);
callbacks->play_speech(samples,3,NULL);
callbacks->process_mark=NULL;
callbacks->word_starts=NULL;
callbacks->word_ends=NULL;
callbacks->sentence_starts=NULL;
callbacks->sentence_ends=NULL;
callbacks->play_audio=NULL;
callbacks->done=NULL;*/
RHVoice_init_params init_params;
char config[]="RHVoice.conf";
char one[]="RHVoice/languages/English/";
char two[]="RHVoice/voices/alan";
//initialize init_params
const char *array[] = {config,two,one,NULL};
init_params.resource_paths=array;
init_params.options=RHVoice_preload_voices;
//assisgn callbacks to init_params
/*init_params.callbacks.set_sample_rate(24000,NULL);
init_params.callbacks.play_speech(samples,3,NULL);
init_params.callbacks.process_mark=NULL;
init_params.callbacks.word_starts=NULL;
init_params.callbacks.word_ends=NULL;
init_params.callbacks.sentence_starts=NULL;
init_params.callbacks.sentence_ends=NULL;
init_params.callbacks.play_audio=NULL;
init_params.callbacks.done=NULL;*/
//initialize a tts_engine
RHVoice_tts_engine ttsengine=RHVoice_new_tts_engine(&init_params);
//debug
QVariant voiceprofnum = RHVoice_get_number_of_voice_profiles(ttsengine);
QVariant voiceprof = RHVoice_get_voices(ttsengine)->name;
QVariant voice = RHVoice_get_number_of_voices(ttsengine);
entrance->debug->setText(voiceprofnum.toString()+","+voiceprof.toString()+","+voice.toString());
//
//initialize synth_params without the voice profile because it causes a crash
RHVoice_synth_params synth;
synth.flags=0;
synth.capitals_mode=RHVoice_capitals_default;
synth.punctuation_mode=RHVoice_punctuation_default;
synth.relative_pitch=1;
synth.relative_volume=1;
synth.relative_rate=1;
synth.absolute_pitch=0;
synth.absolute_volume=1;
synth.absolute_rate=0;
//synth.voice_profile="Alan+Aleksandr";
//
//initialize RHVoice_message which will hold the string i want spoken
RHVoice_message userinput=RHVoice_new_message(ttsengine,"test",4,RHVoice_message_text,&synth,NULL);
RHVoice_speak(userinput);
RHVoice.h
#ifndef RHVOICE_H
#define RHVOICE_H
#include "RHVoice_common.h"
#ifdef __cplusplus
extern "C" {
#else
#include <stddef.h>
#endif
struct RHVoice_tts_engine_struct;
typedef struct RHVoice_tts_engine_struct* RHVoice_tts_engine;
typedef struct
{
/* These are the functions the caller is *required* to provide. */
/* This function will be called first. It will be called again if the sampling rate changes. Return 0 to signal an error. */
int (*set_sample_rate)(int sample_rate,void* user_data);
/* Return 0 to stop synthesis. */
int (*play_speech)(const short* samples,unsigned int count,void* user_data);
/* These functions are optional, */
/* but please make sure to set unused function pointers to 0. */
int (*process_mark)(const char* name,void* user_data);
int (*word_starts)(unsigned int position,unsigned int length,void* user_data);
int (*word_ends)(unsigned int position,unsigned int length,void* user_data);
int (*sentence_starts)(unsigned int position,unsigned int length,void* user_data);
int (*sentence_ends)(unsigned int position,unsigned int length,void* user_data);
int(*play_audio)(const char* src,void *user_data);
void (*done)(void* user_data);
} RHVoice_callbacks;
typedef enum {
RHVoice_preload_voices=1
} RHVoice_init_option;
typedef unsigned int RHVoice_init_options;
typedef struct
{
/* The paths should be encoded as utf-8 strings. */
const char *data_path,*config_path;
/* A list of paths to language and voice data. */
/* It should be used when it is not possible to collect all the data in one place. */
/* The last item in the array should be NULL. */
const char** resource_paths;
RHVoice_callbacks callbacks;
RHVoice_init_options options;
} RHVoice_init_params;
typedef enum {
RHVoice_message_text,
RHVoice_message_ssml,
RHVoice_message_characters,
RHVoice_message_key
} RHVoice_message_type;
struct RHVoice_message_struct;
typedef struct RHVoice_message_struct* RHVoice_message;
typedef struct
{
/* Language code. */
const char* language;
const char* name;
RHVoice_voice_gender gender;
/* Country code. */
const char* country;
} RHVoice_voice_info;
typedef struct
{
/* One of the predefined voice profiles or a custom one, e.g. */
/* Aleksandr+Alan. Voice names should be ordered according to their */
/* priority, but they must not speak the same language. If the */
/* combination includes more than one voice, automatic language */
/* switching may be used. The voice which speaks the primary language */
/* should be placed first. RHVoice will use one of the other voices */
/* from the list, if it detects the corresponding language. The */
/* detection algorithm is not very smart at the moment. It will not */
/* handle languages with common letters. For example, if you set this */
/* field to "CLB+Spomenka", it will always choose CLB for latin */
/* letters. Spomenka might still be used, if Esperanto is requested */
/* through SSML. */
const char* voice_profile;
/* The values must be between -1 and 1. */
/* They are normalized this way, because users can set different */
/* parameters for different voices in the configuration file. */
double absolute_rate,absolute_pitch,absolute_volume;
/* Relative values, in case someone needs them. */
/* If you don't, just set each of them to 1. */
double relative_rate,relative_pitch,relative_volume;
/* Set to RHVoice_punctuation_default to allow the synthesizer to decide */
RHVoice_punctuation_mode punctuation_mode;
/* Optional */
const char* punctuation_list;
/* This mode only applies to reading by characters. */
/* If your program doesn't support this setting, set to RHVoice_capitals_default. */
RHVoice_capitals_mode capitals_mode;
/* Set to 0 for defaults. */
int flags;
} RHVoice_synth_params;
const char* RHVoice_get_version();
RHVoice_tts_engine RHVoice_new_tts_engine(const RHVoice_init_params* init_params);
void RHVoice_delete_tts_engine(RHVoice_tts_engine tts_engine);
unsigned int RHVoice_get_number_of_voices(RHVoice_tts_engine tts_engine);
const RHVoice_voice_info* RHVoice_get_voices(RHVoice_tts_engine tts_engine);
unsigned int RHVoice_get_number_of_voice_profiles(RHVoice_tts_engine tts_engine);
char const * const * RHVoice_get_voice_profiles(RHVoice_tts_engine tts_engine);
int RHVoice_are_languages_compatible(RHVoice_tts_engine tts_engine,const char* language1,const char* language2);
/* Text should be a valid utf-8 string */
RHVoice_message RHVoice_new_message(RHVoice_tts_engine tts_engine,const char* text,unsigned int length,RHVoice_message_type message_type,const RHVoice_synth_params* synth_params,void* user_data);
/* On Windows the library is now built with MSVC instead of Mingw, */
/* so wchar_t will always mean utf-16 there */
RHVoice_message RHVoice_new_message_w(RHVoice_tts_engine tts_engine,const wchar_t* text,unsigned int length,RHVoice_message_type message_type,const RHVoice_synth_params* synth_params,void* user_data);
void RHVoice_delete_message(RHVoice_message message);
int RHVoice_speak(RHVoice_message message);
#ifdef __cplusplus
}
#endif
#endif
I tried setting the synth parameter in new_rhvoice_message function to null but it had no effect.
the voice profile attribute in synth parameters causes the application to crash as well.
Update:
I was told to use rhvoice via speech-dispatcher, and avoid using it directly.
I couldn't figure out how to do that, I have this package installed (rhvoice-speech-dispatcher-plugin.x86_64) on fedora. As far as i know, it doesn't provide any library that I can work with in my project, i can only use it from command line in a terminal.
I'm mentioning this in case it might help someone get closer to figuring this out.
Thank you for your time and help!

C++ trying to cast address to void* and assign to function pointer (so that my bootloader can jump to actual app)

I am writing a bootloader for an STM32, where I need to jump from bootloader to the real app.
In C this works, because I can cast an address to a void pointer and assign that to a function pointer, and call the function pointer as follows:
void jump_to_firmware(uint32_t address)
{
uint32_t reset_handler_add = *((volatile uint32_t *)(address + 4));
void (*app_reset_handler)(void) = (void *)reset_handler_add;
SCB->VTOR = address;
uint32_t msp_value = *((volatile uint32_t *)address);
__set_MSP(msp_value);
app_reset_handler();
}
If I use the same implementation in a C++ the gnu compiler will give an error on the cast to void pointer.
include/bootloader.hpp:58:39: error: invalid conversion from 'void*'
to 'void (*)()' [-fpermissive]
After googling I found this SO page, which I tried and came to the following implementation in my class:
void JumpToApp()
{
// Quick test if C style cast does work
//jump_to_firmware(_appStartAddress);
uint32_t mspAdress = *((volatile uint32_t *)_appStartAddress);
uint32_t resetHandlerAddress = *((volatile uint32_t *)(_appStartAddress + sizeof(uint32_t)));
// https://stackoverflow.com/questions/1096341/function-pointers-casting-in-c
typedef void (*functionPointer)();
functionPointer resetHandler = 0;
reinterpret_cast<void*&>(resetHandler) = (void*)resetHandlerAddress;
SCB->VTOR = _appStartAddress;
__set_MSP(mspAdress);
resetHandler();
}
In the C++ implementation:
functionPointer resetHandler is assigned with 0x8035065
SCB->VTOR is assigned with 0x08020000
mspAddress is assigned with `0x20020000
then the function pointer resetHandler is called
In the C implementation:
app_reset_handler is assigned with 0x8035065
SCB->VTOR is assigned with 0x08020000
mspAddress is assigned with `0x20020000
then the function pointer app_reset_handler is called
The C implementation works, it jumps to my app, the app runs without issues.
The C++ implementation ends up nowhere. It hangs/crashes on the following (to me meaningless) address:
I am trying to keep the amount of source files to a minimum, so I would like to keep the logic in the single class definition.
My questions:
Did I misunderstand the linked SO page and can somebody see where I went wrong in the C++ implementation?
Is there a better/easier way to cast an address to a function pointer in C++?
Or is there a technical reason why it simply can't be done in C++?
PS: The bootloader code is the same in both cases. The only difference I made to test either implementation is to comment out the code in Bootloader::JumpToApp and call the C function jump_to_firmware(uint32_t) instead.
PPS: all peripherals are deinitialized properly. Again, it works fine, the problem only appears when I use this C++ implementation.
The same code will compile in C and C++. You simple has to cast to the correct cast (in C++ you cant assign a void * to non void * pointer. It is much more strict than in C.
void jump_to_firmware(uint32_t address)
{
uint32_t reset_handler_add = *((volatile uint32_t *)(address + 4));
void (*app_reset_handler)(void) = (void (*)(void))reset_handler_add;
/* ... */
}
If you do not like those weird casts you can typedef the function.
typedef void handler(void);
void jump_to_firmware(uint32_t address)
{
uint32_t reset_handler_add = *((volatile uint32_t *)(address + 4));
handler *app_reset_handler = (handler *)reset_handler_add;
/* ... */
}

"ISO C++ forbids initialization in array new": How to directly initialize an template object with its own constructor as an array in C++

So my intention was to build a "Multibuffer" which has a definable amount of "SingleBuffers". The type that is stored is free, so I want to use templates for that reason. I am just playing around a bit.
But I don't know how to initialize the Singlebuffers in the Constructor of the Multibuffer directly.
I won't write down the complete classes, but the Constructors to show the problem. I defined the both classes in the header, as it should be done, when working with template classes.
So my Singlebuffer-Constructor looks like this:
enum BufferState_E
{
BUFFER_WRITE = 0,
BUFFER_READ,
BUFFER_FORCED_READ // buffer is forced for reading
};
template<typename T>
class SingleBuffer
{
public:
/*
* Constructor
* constructs a Buffer with the concrete data field
*/
SingleBuffer( unsigned int buffer_size )
: entry_ptr_ ( new T[buffer_size]() ) //default constructor works?
, end_entry_ptr_ ( &entry_ptr_[buffer_size-1] )
{
read_entry_ptr_ = &entry_ptr_[0];
write_entry_ptr_ = &entry_ptr_[0];
state_ = BUFFER_WRITE;
}
private:
/* The pointer to the buffer */
T * entry_ptr_;
/* the pointers to the entry which is currently read/written */
T *read_entry_ptr_;
T *write_entry_ptr_;
/* the pointer to the end of the buffer */
T * end_entry_ptr_;
/* The state of the buffer */
BufferState_E state_;
}
and my Multibuffer-Constructor which instantiates an amount of Singlebuffers (I wrote a comment after the problematic line of code):
template<typename T>
class MultiBuffer : public BufferBase
{
public:
MultiBuffer( unsigned int buffer_size = 2000 // size of one buffer
, unsigned char number_of_buffers = 5 // how many buffers are there?
, const char* name = "MultiBuffer"
)
: buffer_ptr_ ( new SingleBuffer<T>[number_of_buffers](buffer_size) ) // the problem line!
, end_buffer_ptr_ ( &buffer_ptr_[number_of_buffers-1])
, buffer_size_ ( buffer_size )
, number_of_buffers_ ( number_of_buffers )
{
read_buffer_ptr_ = &buffer_ptr_[0];
write_buffer_ptr_ = &buffer_ptr_[0];
}
private:
/* the normal buffer-pointer */
SingleBuffer<T> *buffer_ptr_;
/* the pointer to the end of the buffers */
SingleBuffer<T> *end_buffer_ptr_;
/* the pointer to the current read-buffer */
SingleBuffer<T> *read_buffer_ptr_;
/* the pointer to the current write-buffer */
SingleBuffer<T> *write_buffer_ptr_;
/* the buffer-size */
unsigned int buffer_size_;
/* the number of buffers */
unsigned char number_of_buffers_;
}
So my Compiler always tells me: "ISO C++ forbids initialization in array new" in the marked line of code. Looking up the cpp-reference for "new" doesn't really help, neither do the other asked questions that have to do with templates.
If I just use the default constructor, like you see in the Singlebuffer initialization it seems to work but as soon as I want to pass a value to the constructor of my own defined template-class it crashes. I did manage to force it to build when not initializing in the Multibuffer-Constructor directly but with a loop which iterates the "number of buffers" and allocates memory in every iteration, but that's not how it should work, besides I don't really know if that really works error-free.
And I don't want to use std::-functions, because I'm working on an embedded system. The compiler is a GCC 4.8.1 and is not changeable too, and lambda-expressions are not supported too...
I hope there will be a possibility. Thanks so far.
The error message says it: You can't provide initialisation in new[]. You will have to assign to those objects later, probably in the body of MultiBuffer::MultiBuffer.
But you shouldn't do that. You should just use std::vector for your dynamic array needs. Your compiler provides it, and the library writers know what they are doing. "Standard library functions are bloated" hasn't been true this century

C++ compilation error: request for member ‘c_cflag' in something not a structure or union

I am trying to compile cp210x USB-UART driver on Debian 7 and getting the following error (when make command):
/var/distr/sillabs/Linux_3.x.x_VCP_Driver_Source/cp210x.c:589:17: error: request for member ‘c_cflag’ in something not a structure or union
Here is a fragment of code, line 589 (starts with &tty->), cp210x.c:
static void cp210x_get_termios(struct tty_struct *tty,
struct usb_serial_port *port)
{
unsigned int baud;
if (tty) {
cp210x_get_termios_port(tty->driver_data,
&tty->termios.c_cflag, &baud);
tty_encode_baud_rate(tty, baud, baud);
} else {
unsigned int cflag;
cflag = 0;
cp210x_get_termios_port(port, &cflag, &baud);
}
}
I think something is wrong with the &tty->termios.c_cflag construction. Please help how to fix it?
Thank you!
It means that in your definition of tty_struct, termios is a structure pointer, not a structure. You need to change the expression
&tty->termios.c_cflag
to
&tty->termios->c_cflag
The definition of tty_struct changed between versions 2.x and 3.x of the Linux kernel.
The driver you're building expects it to contain:
struct ktermios termios, termios_locked;
from 3.x, but you are using the includes from 2.x:
struct ktermios *termios, *termios_locked;
You can either reconsider the kernel you're using to better meet the driver's requirements, or you can hack the driver's code yourself:
- &tty->termios.c_cflag
+ &tty->termios->c_cflag
I would also suggest talking to the driver developer about this, if the requirements are unclear.
a tty_struct contain, among other thing:
// from tty.h
struct tty_struct {
int magic;
// some cut
struct ktermios termios, termios_locked;
// more cut
};
a ktermios in turn, is defined like:
// from termbits.h
struct ktermios {
tcflag_t c_iflag; /* input mode flags */
tcflag_t c_oflag; /* output mode flags */
tcflag_t c_cflag; /* control mode flags */
tcflag_t c_lflag; /* local mode flags */
cc_t c_line; /* line discipline */
cc_t c_cc[NCCS]; /* control characters */
speed_t c_ispeed; /* input speed */
speed_t c_ospeed; /* output speed */
};
and finally, a tcflag_t is:
// also from termbits.h
typedef unsigned int tcflag_t;
so, in conclusion, it should work.
What could muck up that? My first guess would be a macro.
Prime suspect would be that you have a termios macro.
If not that, don't look for the error at line where its reported, it's probably a side-effect of something else.
For example, do you have old headers that the compiler might find instead of those you want? If you are trying to compile a driver for v3 with headers from v2 it wont work.

offsetof() of nested C struct in C++

I'm trying to add a socket filter to one of my sockets in C++ (Linux). In the socket filter I need to get the offset of struct fork_proc_event, which is nested within another structure. The definition looks like this (cn_proc.h):
struct proc_event {
...
union {
...
struct fork_proc_event {
__kernel_pid_t parent_pid;
...
} fork;
...
} event_data;
...
};
In C I would do this:
int off = offsetof(struct fork_proc_event, parent_pid);
However I'm developing in C++. If I try to do this:
int off = offsetof(proc_event::fork_proc_event, parent_pid);
I get the following error:
error: expected type-specifier
error: expected `,'
error: expected `)' before ',' token
How should the offsetof() line look like?
It may help to think of how an implementation of an offsetof macro might go. Here's one example:
#define offsetof(TYPE, MEMBER) \
((uintptr_t)&(((TYPE*)0)->MEMBER))
In other words, using 0 as a pointer to the type you're interested in, and simply taking the address of the struct field...
So if you wanted the offset of parent_pid relative to fork (which is how I initially parsed your question):
((char*)&((struct proc_event*)0)->event_data.fork.parent_pid) - ((char*)&((struct proc_event*)0)->event_data.fork)
On second reading it sounds like you might just want the offset of parent_pid relative to the start of struct proc_event. Adapting the example above that would be:
((uintptr_t)&((struct proc_event*)0)->event_data.fork.parent_pid)
I don't exactly understand the need for all those hacks, when all you have to do is give a name to your nested union type. Any name, just to be able to refer to it in C++ code
struct proc_event {
...
union whatever {
...
struct fork_proc_event {
__kernel_pid_t parent_pid;
...
} fork;
...
} event_data;
...
};
Then you'll be able to refer to it as proc_event::whatever::fork_proc_event in offsetof in C++ code
size_t off = offsetof(proc_event::whatever::fork_proc_event, parent_pid);
If you are interested in offset of parent_pid from the beginning of proc_event, you can do
size_t off = offsetof(proc_event, event_data.fork.parent_pid);
If you cannot change the declaration, you can calculate the offset of parent_pid inside fork_proc_event by doing
size_t off =
offsetof(proc_event, event_data.fork.parent_pid) -
offsetof(proc_event, event_data.fork);
(Although I can't say right away whether the last two are formally legal examples of offsetof usage, they will normally work in practice without any problems.)