I have this structure:
typedef struct edagroup
{
UINT16 nodes; /* # slots - may not all be in use */
EHANDLE *eh; /* ptr to array of node handles */
} *GNUM;
And this:
typedef struct ehandle
{
UINT32 is_tag256; /* Is the remote node 256 character? */
UINT32 is_tag30 ; /* Is the remote node 30 character? */
}*EHANDLE;
And this method:
GNUM sample_call(UINT16 n_nodes, INT16 detect_changes);
We call to this method that returns a GNUM struture and I want to access to is_tag256 property.
Sample:
GNUM FixGroupInit = sample_call(1, 0);
EHANDLE *eh = FixGroupInit->eh;
...
Somebody can help me?
There is not enough information to tell us where the array comes in (and there is an ambiguity in the code comments -- the author of that API ought to be beaten with a stick) but you can try this:
(**(FixGroupInit->eh)).is_tag256
Related
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!
My main code is .ino file for STM32F103C8T6 with STM32 official core. I have also included my library files of .h file and .cpp file.
I want store a values in 2d array called uint32_t Page[15][14]; in .h file of my library
How to store a value in 2d array variable during runtime. I have posted my code below. For me the code below is perfect, but still did not print the value stored in the array by calling the function HatriX_Signal with correct parameters. Kindly let me know what is wrong in my code below.
// .ino file
#include "HATRIX.h"
HATRIX Hatrix;
void setup()
{
Hatrix.HATRIX_INIT(115200);
}
void loop()
{
Hatrix.HatriX_Signal(Temperature_Signal, 0x66, Page[2][0]);
Serial.println(Page[2][0]);
Serial.println((float)Page[2][0] / 100);
}
// .h file
#ifndef HATRIX_H
#define HATRIX_H
#include "Arduino.h"
#include "Thermo_Couple_Input.h"
#define Number_of_Pages 15
#define Number_of_Bytes_Per_Page 64
static Thermo_Couple_Input TC_IN;
static uint32_t Page[Number_of_Pages][(Number_of_Bytes_Per_Page / 4) - 2];
enum Signal { Temperature_Signal,
Pressure_Signal,
Co2_Signal,
Analog_Industrial_Input_Signal,
General_Purpose_Output_Signal,
PWM_Power_Signal,
PWM_Voltage_Signal
};
class HATRIX
{
public:
void HATRIX_INIT(uint32_t bauderate);
void HatriX_Signal(uint8_t Signal, uint8_t I2C_Address, uint32_t Page);
};
#endif
// .cpp file
#include "HATRIX.h"
void HATRIX::HATRIX_INIT(uint32_t bauderate)
{
Serial.begin(bauderate);
}
// \brief Note: The value we get from Thermocouple is float value. So, we multiply the value with 100 and store it in specified static uint32_t Page by user.
// \param enum_Signal choose accordingly from enum signal: { Temperature_Signal ,
// Pressure_Signal ,
// Hatrix.Co2_Signal ,
// Analog_Industrial_Input_Signal ,
// General_Purpose_Output_Signal ,
// PWM_Power_Signal ,
// PWM_Voltage_Signal };
// \param I2C_Address Address of I2C to get the temperature from desired Thermocouple.
// \param Page Give the Page details to store your value. example: Hatrix.Page[4][3]
void HATRIX::HatriX_Signal(uint8_t signal, uint8_t I2C_Address, uint32_t Page)
{
if(signal == Temperature_Signal);
{
TC_IN.Thermo_Couple_Input_Channel(I2C_Address);
Serial.println("Page");
Page = fThermocoupleTemperature * 100;
Serial.println(Page);
}
}
When calling HATRIX::HatriX_Signal(...), you pass a copy of a uint32_t of the multidimensional array Hatrix.Page to the function.
Inside the HATRIX::HatriX_Signal(...) function, you assign a new value to this variable called Page. But since it's just a copy of the value from the array, the array itself won't be effected by this.
In order to get the value of the function you can either use a pointer to the value in the array or a reference to the value in the array, preferably, return the value directly.
Your function could either look like this using a pointer:
void HATRIX::HatriX_Signal(uint8_t signal, uint8_t I2C_Address, uint32_t* Page)
{
if(signal == Temperature_Signal);
{
TC_IN.Thermo_Couple_Input_Channel(I2C_Address);
TC_IN.fThermocoupleTemperature = TC_IN.fThermocoupleTemperature * 100;
Serial.println("Page");
*Page = TC_IN.fThermocoupleTemperature;
Serial.println(*Page);
}
}
and called like:
Hatrix.HatriX_Signal(Hatrix.Temperature_Signal, 0x66, &Hatrix.Page[2][0]);
or look like this using a reference:
void HATRIX::HatriX_Signal(uint8_t signal, uint8_t I2C_Address, uint32_t& Page)
{
if(signal == Temperature_Signal);
{
TC_IN.Thermo_Couple_Input_Channel(I2C_Address);
TC_IN.fThermocoupleTemperature = TC_IN.fThermocoupleTemperature * 100;
Serial.println("Page");
Page = TC_IN.fThermocoupleTemperature;
Serial.println(Page);
}
}
and called like:
Hatrix.HatriX_Signal(Hatrix.Temperature_Signal, 0x66, Hatrix.Page[2][0]);
or alternatively, as I would advice, look like this:
uint32_t HATRIX::HatriX_Signal(uint8_t signal, uint8_t I2C_Address)
{
if(signal == Temperature_Signal);
{
TC_IN.Thermo_Couple_Input_Channel(I2C_Address);
TC_IN.fThermocoupleTemperature = TC_IN.fThermocoupleTemperature * 100;
Serial.println("Page");
uint32_t page = TC_IN.fThermocoupleTemperature;
Serial.println(page);
return page;
}
}
and called like:
Hatrix.Page[2][0] = Hatrix.HatriX_Signal(Hatrix.Temperature_Signal, 0x66);
How to fix this program:
Raw data such as this 2D array should be made private, as per the fundamental OO principle of private encapsulation.
Should you wish the user to access this array it should be done through a "setter" function taking (x,y) coordinates.
Provide a similar "getter" function for read/print access.
HatriX_Signal and similar should not pass along a pointer to data in a class member, because that's nonsense. You already have access to that data through the this pointer.
Generally, I'd advise to read a beginner-level book about C++ and OO, or alternatively ditch C++ completely if you have no intention of using OO program design anyhow.
typedef struct
{
char cStartByte; // Set Cmd 0xB1
int iTotalBytes;
char cSeqNum; // 0 to 99 repeating
char cCommand; //
char cPrintCmd; //
float fData[8]
} CMD,*psCmdOut;
In the code tried many options with no success what to put in ??? to sedn the above structure?
UDPClient1->SendBuffer(EHost->Text,12000, ????);
You can't send your structure as-is using a socket : you need to serialize it. You need to create a common format for data exchange, usually an array of char like this one.
Code :
unsigned char* ToCharArray(psCmdOut s)
{
unsigned char serial[12]; //32-bit arch
serial[0] = s.cStartByte;
/*etc.*/
return serial;
}
You can cast your structure in a (char*) back and forth , but I would advise strongly against it : the implicit conversion hides subtleties like endianness, internal memory padding and alignment, which can blow your system in a unpredictable way.
The answer depends on your version of Indy.
In Indy 8 and 9, SendBuffer() has the following signture:
void __fastcall SendBuffer(String AHost, const int APort, void* ABuffer, const int AByteCount);
So you can do this:
CMD cmd;
// fill cmd as needed...
UDPClient1->SendBuffer(EHost->Text, 12000, &cmd, sizeof(cmd));
In Indy 10, SendBuffer() was changed to take a TIdBytes (dynamic array of bytes) instead:
void __fastcall SendBuffer(const String AHost, const TIdPort APort, const TIdBytes ABuffer);
So you cannot pass the struct pointer directly anymore. However, Indy 10 has a RawToBytes() function to create a TIdBytes from a memory block, so you can do this instead:
CMD cmd;
// fill cmd as needed...
UDPClient1->SendBuffer(EHost->Text, 12000, RawToBytes(&cmd, sizeof(cmd)));
As the #Sam suggested:
UDPClient1->SendBuffer(EHost->Text,12000,reinterpret_cast(&cmd_command));
But the length of the structure is also required. So it will be:
UDPClient1->SendBuffer(EHost->Text,12000,reinterpret_cast<char*>(&cmd_command), sizeof(cmd_command));
And also I think it will be better if you do packing of the structure by adding
#pragma pack(1)
This will give you the actual size of the structure. With this you will be able to send the complete structure. And while receiving on the other side, typecast it back to the same structure.
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.
This is my PER_IO_CONTEXT structure (i stored them in singly linked list):
typedef struct _PER_IO_CONTEXT
{
SLIST_ENTRY ItemEntry;
WSAOVERLAPPED Overlapped;
WSABUF wsabuf;
/* some other data*/
} PER_IO_CONTEXT, *PPER_IO_CONTEXT;
and below is WSAsend , that use the list for getting WSAOVERLAPPED structure:
...
PSLIST_HEADER pListHead;
...
PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(pListHead);
PPER_IO_CONTEXT ovl = (PPER_IO_CONTEXT)pListEntry;
WSASend(pTmp1->Socket,..., &(ovl->Overlapped), NULL);
and the last part when GQCS gets notification:
LPWSAOVERLAPPED lpOverlapped = NULL;
PPER_IO_CONTEXT lpIOContext = NULL;
....
GetQueuedCompletionStatus(..... (LPOVERLAPPED *)&lpOverlapped, INFINITE);
lpIOContext = (PPER_IO_CONTEXT)lpOverlapped;
lpIOContext->wsabuf // this fail
As you can see following cast lpIOContext =(PPER_IO_CONTEXT)lpOverlapped doesn't work because WSAsend was provided with wsaoverlapped - the second member of PER_IO_CONTEXT structure, so dereferences such as lpIOContext-> can't be used in this case.
There is a way to deal with this situation?
To get the address of the corresponding PER_IO_CONTEXT struct you can use this:
lpIOContext = CONTAINING_RECORD(lpOverlapped, PER_IO_CONTEXT, Overlapped);
CONTAINING_RECORD is a macro defined in VC\crt\src\collections.h in such a way:
#define CONTAINING_RECORD(address, type, field) \
((type *)((char *)(address) - (ULONG_PTR)(&((type *)0)->field)))
More information: http://msdn.microsoft.com/en-us/library/windows/hardware/ff542043%28v=vs.85%29.aspx
I'm not sure whether there's a supported mechanism to convert a pointer to a member of a struct to a pointer to the struct. You could cast everything to BYTE * and do the arithmetic, which would work in practice, but depending on your needs it might be cleaner to reorganize to avoid the necessity:
typedef struct _PER_IO_CONTEXT
{
WSAOVERLAPPED Overlapped;
WSABUF wsabuf;
/* some other data*/
} PER_IO_CONTEXT, *PPER_IO_CONTEXT;
typedef struct _PER_IO_CONTEXT_LIST_ITEM
{
SLIST_ENTRY ItemEntry;
PER_IO_CONTEXT Item;
} PER_IO_CONTEXT_LIST_ITEM, *PPER_IO_CONTEXT_LIST_ITEM;