C++ Builder - program end error and localization error - error-handling
I have a problem with a program I have done with Embarcadero C++ Builder.
Part one:
I want to make stand-alone .exe file, and according to that i have disabled "link with dynamic RTL" and disabled "link with runtime packages". But, every time i end my program, I get an error "Abnormal program termination". I've invstigated that and found a partial solution. When I enable link with runtime packages, that error does not appear, but .exe file won't run on PC which don't have C++ builder installed, because some .bpl files missing. So, for now, I have two possibilities: to have "Abnormal program termination" error, or not to have, functional .exe file for all PCs. Except for that error, my program works perfectly.
Part two:
I made fully functional program with 3 units, and I want to translate it on english language using resource DLL wizard. I can preview translated form, but I can't build it, because it say Error but I can't see any more details about error. I really don't know how is it possible to have working program with no errors, and localized version to have an error. I got the advice to do "clean all" and then "build all" but I can't even clean all because of that error.
I really don't know what to do anymore, I am struggling with those problems for a week now and I really hope that someone can help me. Thanks :)
Localization
Not sure if your localization tool is suited for Borland/Embarcadero apps (it might be just for MSVC++ apps which might be the problem).
I do localization on my own (as I needed custom stuff like internal messages and tables translation. So I coded a ~55 KByte parser that takes *.h,*.cpp,*.dfm of all windows as input and creates *.ini file and *.h that will read the selected language ini and translate all forms to it (Caption,Hint,...) then just for each new language I copy the ini and translate the strings. This way I can switch languages on the run without any DLL or restart needed and customers can add new languages on their own without the need for source code or programming skills.
Can not share the code however as it uses some non sharable (corporate) libs of mine for strings,dynamic lists and fast ini file access (they are included in the 55 KByte estimate) but I can share the executable (win32 standalone compiled in BDS2006 and for VCL BDS2006 formatting of code):
Form decode tool v2.70
Use the slow download (it is free without registration). I even add one window in the formulars for testing. You just run the exe and when done use the files from output. However the outputed source files use the fast ini file access (I can not share) so you would need to encode that (or replace with your style access). Here slow winapi based workaround for my ini.h that shoudl work:
#ifndef _ini_h
#define _ini_h
class inifile
{
public:
AnsiString section,filename;
// inline
inifile() {close();}
inifile(inifile& a) { *this=a; }
~inifile() {close();}
inifile* operator = (const inifile *a) { *this=*a; return this; }
//inifile* operator = (const inifile &a) { ...copy... return this; }
int open(AnsiString name) // open ini file
{
close();
if (FileExists(name)) { filename=name; return 1; }
return 0;
}
void close() // close ini file
{
filename="";
section="";
}
int sec_getid(const AnsiString &sec, bool _add) // select section to work with ignoring the returned ID
{
section=sec;
return 0;
}
AnsiString key_get(int section_id,const AnsiString &key,const AnsiString &def) // read key from section of ini with default value
{
if (filename=="") return def;
char dest[1024]; AnsiString val;
GetPrivateProfileString(section.c_str(),key.c_str(),def.c_str(),dest,1024,filename.c_str());
val=dest; return val;
}
};
#endif
So the app has 3 folders:
formulars
put all the *.h,*.cpp;*.dfm files of your forms here. The parsing of *.h is stopping on public: (skip user declarations) to prevent collisions with user code. You can also add comments to end of component line:
// LANGUAGE_SKIP_CAPT
// LANGUAGE_SKIP_TEXT
// LANGUAGE_SKIP_HINT
or any combination to prevent translation is messing with it.
messages
Ignore this it is for *.cpp source files with internal messages _messages[]to translate must be properly encoded using markers in comments like this:
AnsiString _messages[_msg_enum_end+1]=
{
// LANGUAGE_MSG000_TEXT_BEG
"Error: message id out of range !!!",
"OpenGL FBO support is missing !!! ... switching to simplified graphics",
"OpenGL VBO support is missing !!! ... switching to simplified graphics",
"Sorry: ATI graphic card detected !!! ... switching to simplified graphics",
"Sorry: ATI Radeon HD 5450 graphic card detected !!! ... disabling preview features",
"Done.",
// LANGUAGE_MSG000_TEXT_END
"",
""
};
output
the app here outputs 4 files
init.h can ignore this it is just init/exit load/stroing of window state
init.ini ini file for the init can ignore this
into app ini.
language.h this is what you want it is the translation routine
english.ini translation ini file using current window texts
Here example of generated language.h:
#include <math.h>
#include "ini.h" // use the ini.h above
void language_init(AnsiString name)
{
int sec;
inifile ini;
ini.open(name);
sec=ini.sec_getid("Twin_EditorSetup",true);
win_EditorSetup->ck_specchar->Caption=ini.key_get(sec,"C_ck_specchar","Special chars.");
win_EditorSetup->ck_specchar->Hint =ini.key_get(sec,"H_ck_specchar","View special characters on/off");
win_EditorSetup->cb_colors->Hint =ini.key_get(sec,"H_cb_colors","Select color for editing");
win_EditorSetup->ed_tabs->Text =ini.key_get(sec,"T_ed_tabs","1");
win_EditorSetup->ed_tabs->Hint =ini.key_get(sec,"H_ed_tabs","Tabulator size");
win_EditorSetup->ck_smart->Caption=ini.key_get(sec,"C_ck_smart","Smart eol");
win_EditorSetup->ck_smart->Hint =ini.key_get(sec,"H_ck_smart","Delete empty space at end of edited line");
win_EditorSetup->RadioGroup1->Caption=ini.key_get(sec,"C_RadioGroup1","");
win_EditorSetup->RadioGroup1->Hint =ini.key_get(sec,"H_RadioGroup1","");
win_EditorSetup->rb_eol1310->Caption=ini.key_get(sec,"C_rb_eol1310","CR LF");
win_EditorSetup->rb_eol1310->Hint =ini.key_get(sec,"H_rb_eol1310","EOL CR LF 13 10");
win_EditorSetup->rb_eol13->Caption=ini.key_get(sec,"C_rb_eol13","CR");
win_EditorSetup->rb_eol13->Hint =ini.key_get(sec,"H_rb_eol13","EOL CR 13");
win_EditorSetup->rb_eol10->Caption=ini.key_get(sec,"C_rb_eol10","LF");
win_EditorSetup->rb_eol10->Hint =ini.key_get(sec,"H_rb_eol10","EOL LF 10");
win_EditorSetup->txt_tabs->Caption=ini.key_get(sec,"C_txt_tabs","TAB:");
win_EditorSetup->txt_tabs->Hint =ini.key_get(sec,"H_txt_tabs","");
win_EditorSetup->pan_color->Caption=ini.key_get(sec,"C_pan_color","");
win_EditorSetup->pan_color->Hint =ini.key_get(sec,"H_pan_color","Pick color");
sec=ini.sec_getid("Global",true);
ini.close();
}
so in your main app form cpp include language.h but after its pointer is declared (after line like TForm1 *Form1; ) otherwise you will get access violation erros. Now call language_init with selected language ini file on any language change or Apps init like this:
if (Form1->Visible) language_init(ExtractFilePath(Application->ExeName)+"english.ini");
you need to specify full path if winapi is used for the ini.h !!!
Packages
Hard to say without MCVE. You most likely use non standard 3th party package and or have a bug in the code. My bet is you got memory leaks which tend to make a such errors time to time (especially on exit of app) try to use CodeGuard in the Project options which will show you runtime errors and allow you to debug them much better but it will not work for huge projects. Also if you are on older compiler or need to debug the memory leaks see these:
traceback a pointer in c++ code
BDS 2006 C++ hidden memory manager conflicts
They might solve your issues (even those you did not know of yet)
P.S.
If you're interested here is the main source for this tool (but without the supporting *.h files it will not work but you can see how it work in case you want to encode this on your own:
//--- Formular decoder storage class ver 2.40 -------------------------------
#ifndef _frm_decode_h
#define _frm_decode_h
//---------------------------------------------------------------------------
const int _frm_cmp_prop_none =0x00000000;
// language properties
const int _frm_cmp_prop_capt =0x00000001;
const int _frm_cmp_prop_text =0x00000002;
const int _frm_cmp_prop_hint =0x00000004;
// ini properties
const int _frm_cmp_prop_align =0x00010000;
const int _frm_cmp_prop_pos =0x00020000;
const int _frm_cmp_prop_check =0x00040000;
const int _frm_cmp_prop_down =0x00080000;
const int _frm_cmp_prop_page =0x00100000;
class _frm_component
{
public:
AnsiString name; // name in C++
int prop; // component class enum
int action; // if true do not save/load by language
};
_frm_component frm_component[]=
{
// standard
"TMenuItem" ,_frm_cmp_prop_capt|_frm_cmp_prop_hint|_frm_cmp_prop_align|_frm_cmp_prop_check,0,
"TLabel" ,_frm_cmp_prop_capt|_frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
"TEdit" ,_frm_cmp_prop_text|_frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
"TMemo" , _frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
"TButton" ,_frm_cmp_prop_capt|_frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
"TCheckBox" ,_frm_cmp_prop_capt|_frm_cmp_prop_hint|_frm_cmp_prop_align|_frm_cmp_prop_check,0,
"TRadioButton" ,_frm_cmp_prop_capt|_frm_cmp_prop_hint|_frm_cmp_prop_align|_frm_cmp_prop_check,0,
"TListBox" , _frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
"TComboBox" , _frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
"TScrollBar" , _frm_cmp_prop_hint|_frm_cmp_prop_align|_frm_cmp_prop_pos ,0,
"TGroupBox" ,_frm_cmp_prop_capt|_frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
"TRadioGroup" ,_frm_cmp_prop_capt|_frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
"TPanel" ,_frm_cmp_prop_capt|_frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
"TAction" ,_frm_cmp_prop_capt|_frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
// additional
"TBitBtn" ,_frm_cmp_prop_capt|_frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
"TSpeedButton" ,_frm_cmp_prop_capt|_frm_cmp_prop_hint|_frm_cmp_prop_align|_frm_cmp_prop_down ,0,
"TStringGrid" , _frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
"TCategoryButtons" , _frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
// win32
"TProgressBar" , _frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
// system
"TPaintBox" , _frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
// win3.1
"TTabbedNotebook" , _frm_cmp_prop_hint|_frm_cmp_prop_align|_frm_cmp_prop_page ,0,
"TFileListBox" , _frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
"TDirectoryListBox" , _frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
"TDriveComboBox" , _frm_cmp_prop_hint|_frm_cmp_prop_align ,0,
"",0,0
};
//---------------------------------------------------------------------------
class frm_decode
{
public:
AnsiString form; // formular class name in C++
struct _component:_frm_component
{
// language properties
AnsiString text,hint;
// init properties
AnsiString align; // -only for internal init purposes
AnsiString checked,down,position,left,top,width,height;
int skip; // znacky
void reset()
{
text="";
hint="";
align="alNone";
checked="False";
down="False";
position="1";
left="0";
top="0";
width="1";
height="1";
skip=0;
}
};
struct _message { AnsiString id,txt; };
List<_component> cmp;
List<_message> msg;
frm_decode(){ reset(); }
void reset() { form=""; cmp.reset(); msg.reset(); }
void load_form(AnsiString file); // load formular (file.h, file.dfm)
void load_msg(AnsiString file); // load messages (file.h, file.cpp)
void save_lang_ini(inifile &ini); // save language to ini
void save_init_ini(inifile &ini); // save initialisation to ini
void save_lang_cpp(AnsiString &txt,bool end=true); // save language loader (C++) to txt
void save_init_cpp(AnsiString &txt,bool end=true); // save init loader (C++) to txt
void save_exit_cpp(AnsiString &txt,bool end=true); // save exit saver (C++) to txt
};
//---------------------------------------------------------------------------
void frm_decode::load_form(AnsiString file)
{
// nepodporuje "/* ... */"
int hnd,adr,siz,i,j,l,e,_skip;
AnsiString lin,s,s0,ss;
_component a;
BYTE *txt;
reset();
// load list of components from: file.h
hnd=FileOpen(file+".h",fmOpenRead);
if (hnd<0) return;
siz=FileSeek(hnd,0,2);
FileSeek(hnd,0,0);
txt=new BYTE[siz];
if (txt==NULL) { FileClose(hnd); return; }
FileRead(hnd,txt,siz);
FileClose(hnd);
for (adr=0;adr<siz;)
{
lin=txt_load_lin(txt,siz,adr,true);
l=lin.Length();
for (_skip=0;i<=l;) // osetri zacky este pred odrezanim pokecu
{
s=str_load_str(lin,i,true);
if (s=="LANGUAGE_SKIP_CAPT") _skip|=_frm_cmp_prop_capt;
if (s=="LANGUAGE_SKIP_TEXT") _skip|=_frm_cmp_prop_text;
if (s=="LANGUAGE_SKIP_HINT") _skip|=_frm_cmp_prop_hint;
}
if (str_is_mask(lin,"*//*")) { s=lin; lin=""; for (i=1;i<l;i++) if ((s[i]=='/')&&(s[i+1]=='/')) break; else lin+=char(s[i]); l=lin.Length(); }
s=""; s0=""; e=0;
for (i=1;i<=l;)
{
s0=s;
s=str_load_str(lin,i,true);
if (s=="private:") // stop processing for non formular symbols
{
adr=siz; break;
}
if (!e) { e=1; continue; }
if (s0=="class")
{
form=s;
continue;
}
if (s!="")
for (j=0;;j++)
{
if (frm_component[j].name=="") break;
if (frm_component[j].name==s0)
{
a.reset();
a.name="";
if (s[1]!='*') s=" "+s;
for (int q=2;q<=s.Length();q++) a.name+=s[q];
a.prop=frm_component[j].prop;
a.action=0;
a.skip=_skip;
cmp.add(a);
break;
}
}
}
}
delete txt;
// load component properties from: file.dfm
int cmpid=-1;
hnd=FileOpen(file+".dfm",fmOpenRead);
if (hnd<0) return;
siz=FileSeek(hnd,0,2);
FileSeek(hnd,0,0);
txt=new BYTE[siz];
if (txt==NULL) { FileClose(hnd); return; }
FileRead(hnd,txt,siz);
FileClose(hnd);
for (adr=0;adr<siz;)
{
lin=txt_load_lin(txt,siz,adr,true);
l=lin.Length();
for (i=1;i<=l;i++) // if cutted '' line then continue
if (lin[i]>32)
{
if (lin[i]!='\'') i=-1;
break;
}
if (i<0) { s=""; s0=""; e=0; } // else new line
for (i=1;i<=l;)
{
int q=1;
if (s!="")
if (s[1]=='\'')
{
if (s[s.Length()]!='\'')
{
s+=" "+str_load_str(lin,i,true);
if (s[s.Length()]!='\'') continue;
}
q=0;
}
if (q)
{
int qqq=0; // handle cutted '' line
ss=str_load_str(lin,i,true);
if ((s0!="")&&((ss!="")&&(ss[1]=='\''))) { qqq=1; s+=ss; }
if ((s0!="")&&(ss=="+")) { qqq=1; }
if (!qqq) { s0=s; s=ss; }
if (s!="")
if (s[1]=='\'')
if (s[s.Length()]!='\'')
e=0;
}
/* // odstran ''
if (s!="")
if (s[1]=='\'')
if (s[s.Length()]=='\'')
{ ss=""; for (q=2;q<s.Length();q++) ss+=s[q]; s=ss; }
*/
if (!e) { e=1; continue; }
if (s!="")
if (s0=="object")
{
cmpid=-1;
if (s[s.Length()]==':')
{
AnsiString t=s;
s=""; for (j=1;j<t.Length();j++) s+=char(t[j]);
}
for (j=0;j<cmp.num;j++)
if (cmp[j].name==s)
{
cmpid=j;
break;
}
continue;
}
if (cmpid<0) continue;
char aa;
bool tt;
int ii,cc,ll=s.Length();
if (ll>0)
{
ss="";
tt=false;
for (ii=1;ii<=ll;ii++)
{
aa=s[ii];
if (aa=='\'') { tt=!tt; continue; }
if (tt) { ss+=aa; continue; }
if (aa!='#'){ ss+=aa; continue; }
cc=0;
for (ii++;ii<=ll;ii++)
{
aa=s[ii];
if (aa=='\'') { ii--; break; }
if (aa< '0') { ii--; break; }
if (aa> '9') { ii--; break; }
cc*=10; cc+=aa-'0';
}
ss+=char(cc);
}
s=ss;
}
if (s0=="Action" ) cmp[cmpid].action=1;
if (s0=="Caption" ) cmp[cmpid].text=s;
if (s0=="Text" ) cmp[cmpid].text=s;
if (s0=="Hint" ) cmp[cmpid].hint=s;
if (s0=="Align" ) cmp[cmpid].align=s;
if (s0=="Checked" ) cmp[cmpid].checked=s;
if (s0=="Down" ) cmp[cmpid].down=s;
if (s0=="Position") cmp[cmpid].position=s;
if (s0=="Left" ) cmp[cmpid].left=s;
if (s0=="Top" ) cmp[cmpid].top=s;
if (s0=="Width" ) cmp[cmpid].width=s;
if (s0=="Height" ) cmp[cmpid].height=s;
}
}
delete txt;
// load list of messages from: file.cpp
load_msg(file+".cpp");
}
//---------------------------------------------------------------------------
void frm_decode::load_msg(AnsiString file)
{
// nepodporuje "/* ... */"
int hnd,adr,siz,i,l,e;
AnsiString lin,s;
BYTE *txt;
hnd=FileOpen(file,fmOpenRead);
if (hnd<0) return;
siz=FileSeek(hnd,0,2);
FileSeek(hnd,0,0);
txt=new BYTE[siz];
if (txt==NULL) { FileClose(hnd); return; }
FileRead(hnd,txt,siz);
FileClose(hnd);
e=msg.num;
for (adr=0;adr<siz;)
{
lin=txt_load_lin(txt,siz,adr,true);
l=lin.Length();
for (i=1;i<=l;)
{
s=str_load_str(lin,i,true);
if (s=="_msg_enum_beg")
for (;adr<siz;)
{
lin=txt_load_lin(txt,siz,adr,true);
l=lin.Length();
for (i=1;i<=l;)
{
s=str_load_str(lin,i,true);
if (s=="_msg_enum_end") { adr=siz; i=l+1; break; }
if (str_is_mask(s,"_msg*"))
{
_message m;
m.id=s;
m.txt="";
msg.add(m);
}
}
}
}
}
for (adr=0;adr<siz;)
{
lin=txt_load_lin(txt,siz,adr,true);
l=lin.Length();
for (i=1;i<=l;)
{
s=str_load_str(lin,i,true);
if (s=="_messages[_msg_enum_end+1]")
for (;adr<siz;)
{
if (e>=msg.num) break;
s="";
for (;adr<siz;adr++)
if (txt[adr]=='"')
{
adr++;
for (;adr<siz;adr++)
if (txt[adr]=='"')
{
adr++;
msg[e].txt=s;
e++;
break;
}
else s+=char(txt[adr]);
break;
}
}
}
}
delete txt;
}
//---------------------------------------------------------------------------
void frm_decode::save_lang_ini(inifile &ini)
{
int i,p,s,sec;
AnsiString key,val;
sec=ini.sec_getid(form,true);
for (i=0;i<msg.num;i++) ini.key_set(sec,msg[i].id,msg[i].txt);
for (i=0;i<cmp.num;i++)
{
if (cmp[i].action) continue;
key=cmp[i].name;
p=cmp[i].prop;
s=cmp[i].skip;
if ((int(p&_frm_cmp_prop_capt)!=0)&&(int(s&_frm_cmp_prop_capt)==0)) ini.key_set(sec,"C_"+key,cmp[i].text);
if ((int(p&_frm_cmp_prop_text)!=0)&&(int(s&_frm_cmp_prop_text)==0)) ini.key_set(sec,"T_"+key,cmp[i].text);
if ((int(p&_frm_cmp_prop_hint)!=0)&&(int(s&_frm_cmp_prop_hint)==0)) ini.key_set(sec,"H_"+key,cmp[i].hint);
}
}
//---------------------------------------------------------------------------
void frm_decode::save_init_ini(inifile &ini)
{
int i,p,sec;
AnsiString key,val;
sec=ini.sec_getid(form,true);
for (i=0;i<cmp.num;i++)
{
if (cmp[i].action) continue;
key=cmp[i].name;
p=cmp[i].prop;
if (cmp[i].align=="alLeft") ini.key_set(sec,"XS_"+key,cmp[i].width);
if (cmp[i].align=="alRight") ini.key_set(sec,"XS_"+key,cmp[i].width);
if (cmp[i].align=="alTop") ini.key_set(sec,"YS_"+key,cmp[i].height);
if (cmp[i].align=="alBottom") ini.key_set(sec,"YS_"+key,cmp[i].height);
if (cmp[i].align=="alClient")
{
}
if (cmp[i].align=="alNone")
{
/*
ini.key_set(sec,"X0_"+key,cmp[i].left);
ini.key_set(sec,"Y0_"+key,cmp[i].top);
ini.key_set(sec,"XS_"+key,cmp[i].width);
ini.key_set(sec,"YS_"+key,cmp[i].height);
*/
}
if (int(p&_frm_cmp_prop_check )!=0) ini.key_set(sec,"CHK_"+key,(cmp[i].checked=="True")?"1":"0");
if (int(p&_frm_cmp_prop_down )!=0) ini.key_set(sec,"DWN_"+key,(cmp[i].down =="True")?"1":"0");
if (int(p&_frm_cmp_prop_pos )!=0) ini.key_set(sec,"POS_"+key, cmp[i].position );
}
}
//---------------------------------------------------------------------------
void frm_decode::save_lang_cpp(AnsiString &txt,bool end)
{
int i,p,s;
AnsiString cpp,lin,key,frm,tabl,endl;
tabl=char(9); endl=char(13); endl+=char(10);
cpp="";
if (txt=="")
{
lin="";
lin+="#include <math.h>"+endl;
lin+="#include \"ini.h\""+endl+endl;
lin+="void language_init(AnsiString name)"+endl;
lin+=tabl+"{"+endl;
lin+=tabl+"int sec;"+endl;
lin+=tabl+"inifile ini;"+endl;
lin+=tabl+"ini.open(name);"+endl;
cpp+=lin;
}
frm=""; for (i=2;i<=form.Length();i++) frm+=form[i];
cpp+=endl;
cpp+=tabl+"sec=ini.sec_getid(\""+form+"\",true);"+endl;
for (i=0;i<msg.num;i++)
{
lin=tabl+"_messages[";
if (i<100) lin+=" ";
if (i<10) lin+=" ";
lin+=i;
lin+="]=ini.key_get(sec,\""+msg[i].id+"\",\""+msg[i].txt+"\");"+endl;
cpp+=lin;
}
for (i=0;i<cmp.num;i++)
{
if (cmp[i].action) continue;
key=cmp[i].name;
p=cmp[i].prop;
s=cmp[i].skip;
lin="";
if ((int(p&_frm_cmp_prop_capt)!=0)&&(int(s&_frm_cmp_prop_capt)==0)) lin+=tabl+frm+"->"+key+"->Caption=ini.key_get(sec,\"C_"+key+"\",\""+cmp[i].text+"\");"+endl;
if ((int(p&_frm_cmp_prop_text)!=0)&&(int(s&_frm_cmp_prop_text)==0)) lin+=tabl+frm+"->"+key+"->Text =ini.key_get(sec,\"T_"+key+"\",\""+cmp[i].text+"\");"+endl;
if ((int(p&_frm_cmp_prop_hint)!=0)&&(int(s&_frm_cmp_prop_hint)==0)) lin+=tabl+frm+"->"+key+"->Hint =ini.key_get(sec,\"H_"+key+"\",\""+cmp[i].hint+"\");"+endl;
cpp+=lin;
}
if (end)
{
lin=endl;
lin+=tabl+"ini.close();"+endl;
lin+=tabl+"}"+endl;
cpp+=lin;
}
txt+=cpp;
}
//---------------------------------------------------------------------------
void frm_decode::save_init_cpp(AnsiString &txt,bool end)
{
int i,p;
AnsiString cpp,lin,key,frm,tabl,endl,endlx;
tabl=char(9); endl=char(13); endl+=char(10); endlx="\\"+endl;
cpp="";
if (txt=="")
{
lin="";
lin+="//---------------------------------------------------------------------------"+endl;
lin+="#include <math.h>"+endl;
lin+="#include \"ini.h\""+endl;
lin+="//---------------------------------------------------------------------------"+endl;
lin+="#define _def_program_init(name) for(;;)"+endlx;
lin+=tabl+"{"+endlx;
lin+=tabl+"int sec;"+endlx;
lin+=tabl+"inifile ini;"+endlx;
lin+=tabl+"ini.open(name);"+endlx;
// lin+=tabl+"if (!ini.open(name)) break;"+endlx;
cpp+=lin;
}
frm=""; for (i=2;i<=form.Length();i++) frm+=form[i];
cpp+=tabl+"sec=ini.sec_getid(\""+form+"\",true);"+endlx;
for (i=0;i<cmp.num;i++)
{
if (cmp[i].action) continue;
key=cmp[i].name;
p=cmp[i].prop;
lin="";
if (cmp[i].align=="alLeft") lin+=tabl+frm+"->"+key+"->Width =ini.key_geti(sec,\"XS_"+key+"\","+cmp[i].width +");"+endlx;
if (cmp[i].align=="alRight") lin+=tabl+frm+"->"+key+"->Width =ini.key_geti(sec,\"XS_"+key+"\","+cmp[i].width +");"+endlx;
if (cmp[i].align=="alTop") lin+=tabl+frm+"->"+key+"->Height=ini.key_geti(sec,\"YS_"+key+"\","+cmp[i].height+");"+endlx;
if (cmp[i].align=="alBottom") lin+=tabl+frm+"->"+key+"->Height=ini.key_geti(sec,\"YS_"+key+"\","+cmp[i].height+");"+endlx;
if (cmp[i].align=="alClient")
{
}
if (cmp[i].align=="alNone")
{
/*
lin+=tabl+frm+"->"+key+"->Left =ini.key_geti(sec,\"X0_"+key+"\","+cmp[i].left +");"+endlx;
lin+=tabl+frm+"->"+key+"->Top =ini.key_geti(sec,\"Y0_"+key+"\","+cmp[i].top +");"+endlx;
lin+=tabl+frm+"->"+key+"->Width =ini.key_geti(sec,\"XS_"+key+"\","+cmp[i].width +");"+endlx;
lin+=tabl+frm+"->"+key+"->Height=ini.key_geti(sec,\"YS_"+key+"\","+cmp[i].height+");"+endlx;
*/
}
if (int(p&_frm_cmp_prop_check )!=0) lin+=tabl+frm+"->"+key+"->Checked =ini.key_geti(sec,\"CHK_"+key+"\","+cmp[i].checked +");"+endlx;
if (int(p&_frm_cmp_prop_down )!=0) lin+=tabl+frm+"->"+key+"->Down =ini.key_geti(sec,\"DWN_"+key+"\","+cmp[i].down +");"+endlx;
if (int(p&_frm_cmp_prop_pos )!=0) lin+=tabl+frm+"->"+key+"->Position=ini.key_geti(sec,\"POS_"+key+"\","+cmp[i].position+");"+endlx;
cpp+=lin;
}
if (end)
{
lin+=tabl+"ini.close();"+endlx;
lin+=tabl+"break;"+endlx;
lin+=tabl+"}"+endl;
cpp+=lin;
}
txt+=cpp;
}
//---------------------------------------------------------------------------
void frm_decode::save_exit_cpp(AnsiString &txt,bool end)
{
int i,p;
AnsiString cpp,lin,key,frm,tabl,endl,endlx;
tabl=char(9); endl=char(13); endl+=char(10); endlx="\\"+endl;
cpp="";
if (txt=="")
{
lin+="//---------------------------------------------------------------------------"+endl;
lin+="#define _def_program_exit(name) for(;;)"+endlx;
lin+=tabl+"{"+endlx;
lin+=tabl+"int sec;"+endlx;
lin+=tabl+"inifile ini;"+endlx;
lin+=tabl+"ini.open(name);"+endlx;
cpp+=lin;
}
frm=""; for (i=2;i<=form.Length();i++) frm+=form[i];
cpp+=tabl+"sec=ini.sec_getid(\""+form+"\",true);"+endlx;
for (i=0;i<cmp.num;i++)
{
if (cmp[i].action) continue;
key=cmp[i].name;
p=cmp[i].prop;
lin="";
if (cmp[i].align=="alLeft") lin+=tabl+"ini.key_set(sec,\"XS_"+key+"\","+frm+"->"+key+"->Width );"+endlx;
if (cmp[i].align=="alRight") lin+=tabl+"ini.key_set(sec,\"XS_"+key+"\","+frm+"->"+key+"->Width );"+endlx;
if (cmp[i].align=="alTop") lin+=tabl+"ini.key_set(sec,\"YS_"+key+"\","+frm+"->"+key+"->Height);"+endlx;
if (cmp[i].align=="alBottom") lin+=tabl+"ini.key_set(sec,\"YS_"+key+"\","+frm+"->"+key+"->Height);"+endlx;
if (cmp[i].align=="alClient")
{
}
if (cmp[i].align=="alNone")
{
/*
lin+=tabl+"ini.key_set(sec,\"X0_"+key+"\","+frm+"->"+key+"->Left );"+endlx;
lin+=tabl+"ini.key_set(sec,\"Y0_"+key+"\","+frm+"->"+key+"->Top );"+endlx;
lin+=tabl+"ini.key_set(sec,\"XS_"+key+"\","+frm+"->"+key+"->Width );"+endlx;
lin+=tabl+"ini.key_set(sec,\"YS_"+key+"\","+frm+"->"+key+"->Height);"+endlx;
*/
}
if (int(p&_frm_cmp_prop_check )!=0) lin+=tabl+"ini.key_set(sec,\"CHK_"+key+"\",int("+frm+"->"+key+"->Checked));"+endlx;
if (int(p&_frm_cmp_prop_down )!=0) lin+=tabl+"ini.key_set(sec,\"DWN_"+key+"\",int("+frm+"->"+key+"->Down ));"+endlx;
if (int(p&_frm_cmp_prop_pos )!=0) lin+=tabl+"ini.key_set(sec,\"POS_"+key+"\", "+frm+"->"+key+"->Position);"+endlx;
cpp+=lin;
}
if (end)
{
lin+=tabl+"ini.save(name);"+endlx;
lin+=tabl+"ini.close();"+endlx;
lin+=tabl+"break;"+endlx;
lin+=tabl+"}"+endl;
lin+="//---------------------------------------------------------------------------"+endl;
cpp+=lin;
}
txt+=cpp;
}
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
Related
Port not bound SystemC (E112)
I am trying to implement a producer (master) speaking to a memory element (slave) through the memory controller (which implements the interface simple_mem_interface). Note: Some functions details and include statements are not fully mentioned in the code attached. Searching for bugs in the code. Adding debugging tools to find the fault in Write Enable Port. binding.cpp int sc_main(int argc, char* argv[]) { sc_signal<unsigned int> d_out,d_in,address_d; sc_signal<bool> wen, ren, ack; sc_clock ClkFast("ClkFast", 100, SC_NS); sc_clock ClkSlow("ClkSlow", 50, SC_NS); Memory_Controller Controller1 ("Controller"); d_out = Controller1.data_mem_read; ren.write(Controller1.REN); ack.write(Controller1.ack); d_in.write(Controller1.data_write); address_d.write(Controller1.address); wen.write(Controller1.WEN); producer P1("Producer"); P1.out(Controller1); P1.Clk(ClkFast); Memory_module MEM("Memory"); MEM.Wen(wen); MEM.Ren(ren); MEM.ack(ack); MEM.Clock(ClkSlow); MEM.data_in(d_in); MEM.data_out(d_out); MEM.address(address_d); sc_start(5000, SC_NS); return 0; Memory_controller.h #define MEM_SIZE 100 #include <interface_func.h> class Memory_Controller : public sc_module, public simple_mem_if { public: // Ports sc_in <unsigned int> data_mem_read{ "Data_Read_from_Memory" }; sc_out<bool> REN { "Read_Enable" }; sc_out<bool> WEN { "Write_Enable" }; sc_out <bool> ack{ "ACK_Bool" }; sc_out<unsigned int> address{ "Memory_Address" }, data_write{ "Data_Written_to_Memory" }; // constructor Memory_Controller(sc_module_name nm) : sc_module(nm) { // Creating a 2 dimentional array holding adresses and data WEN.write(false); REN.write(false); ack.write(false); } ~Memory_Controller() //destructor { } bool Write(unsigned int address_i, unsigned int datum) // blocking write { WEN.write(true); REN.write(false); data_write.write(datum); address.write(address_i); if (ack == true) return true; else return false; } bool Read(unsigned int address_i, unsigned int& datum_i) // blocking read { WEN.write(false); REN.write(true); datum_i=data_mem_read; address.write(address_i); if (ack == true) return true; else return false; } void register_port(sc_port_base& port, const char* if_typename) { cout << "binding " << port.name() << " to " << "interface: " << if_typename << endl; } }; Memory.h #define MEM_SIZE 100 #include "interface_func.h" class Memory_module : public sc_module { public: sc_in<bool> Wen,Ren; sc_in <unsigned int> address, data_in ; sc_in<bool> Clock; sc_out <unsigned int> data_out; sc_out <bool> ack; bool fileinput = false; ifstream myfile; unsigned int item [MEM_SIZE]; Memory_module() { } void Write() // blocking write { while (true) { wait(); if (Wen==true) { if (address >= MEM_SIZE || address < 0) { ack=false; } else { item[address]=data_in; ack=true; } } } } void Read() // blocking read { while (true) { wait(); if (Ren) { if (address >= MEM_SIZE || address < 0) ack=false; else { data_out.write(item[address]); ack=true; } } } } SC_CTOR(Memory_module) { SC_THREAD(Read); sensitive << Clock.pos(); SC_THREAD(Write); sensitive << Clock.pos(); } }; interface_func.h class simple_mem_if : virtual public sc_interface { public: virtual bool Write(unsigned int addr, unsigned int data) = 0; virtual bool Read(unsigned int addr, unsigned int& data) = 0; }; After debugging the SystemC binder.cpp code, the following error arises: (E112) get interface failed: port is not bound : port 'Controller.Write_Enable' (sc_out)
You cannot drive your unconnected ports in the Memory_Controller constructor. If you want to explicitly drive these ports during startup, move these calls to a start_of_simulation callback: Memory_Controller(sc_module_name nm) : sc_module(nm) {} void start_of_simulation() { WEN.write(false); REN.write(false); ack.write(false); }
How to io_control of boost library socket with customized command
I' trying to make an identical function to "ioctl" in c++ style using boost library. Here is my "c" style code: int sockfd; char * id; struct iwreq wreq; memset(&wreq, 0, sizeof(struct iwreq)); sprintf(wreq.ifr_name, IW_INTERFACE); if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { fprintf(stderr, "Cannot open socket \n"); fprintf(stderr, "errno = %d \n", errno); fprintf(stderr, "Error description is : %s\n",strerror(errno)); exit(1); } printf("Socket opened successfully \n"); id = malloc(IW_ESSID_MAX_SIZE+1); wreq.u.essid.pointer = id; if (ioctl(sockfd, SIOCGIWESSID, &wreq)) { fprintf(stderr, "Get ESSID ioctl failed \n"); fprintf(stderr, "errno = %d \n", errno); fprintf(stderr, "Error description : %s\n",strerror(errno)); exit(2); } printf("IOCTL Successfull\n"); printf("ESSID is %s\n", wreq.u.essid.pointer); I found some relevant example, but I'm not clear how to use it correctly. example Main function: boost::asio::ip::udp::socket socket(io_service); struct iwreq wreq memset(&wreq, 0, sizeof(struct iwreq)); sprintf(wreq.ifr_name, IW_INTERFACE); id = malloc(IW_ESSID_MAX_SIZE+1); wreq.u.essid.pointer = id; boost::asio::detail::io_control::myCommand command; command.set(&wreq); boost::system::error_code ec; socket.io_control(command, ec); if (ec) { // An error occurred. } Custom command: #include <boost/asio/detail/config.hpp> #include <cstddef> #include <boost/config.hpp> #include <boost/asio/detail/socket_types.hpp> #include <boost/asio/detail/push_options.hpp> namespace boost { namespace asio { namespace detail { namespace io_control { // I/O control command for getting number of bytes available. class myCommand { public: // Default constructor. myCommand() : value_(0) { } // Get the name of the IO control command. int name() const { return static_cast<int>(SIOCGIWESSID); } // Set the value of the I/O control command. void set(struct iwreq* value) { value_ = static_cast<detail::ioctl_arg_type>(value); } // Get the current value of the I/O control command. std::size_t get() const { return static_cast<struct iwreq*>(value_); } // Get the address of the command data. detail::ioctl_arg_type* data() { return &value_; } // Get the address of the command data. const detail::ioctl_arg_type* data() const { return &value_; } private: detail::ioctl_arg_type value_; }; } // namespace io_control } // namespace detail } // namespace asio } // namespace boost However, the code does not work. If you have any example code or solution, please let me know. Thank you.
How to notify ListView that DataModel has changed
I created a ListView and I want to use it with a custom DataModel. However, I have a problem: at the moment the view gets created, I don't have the data loaded into the model. The model data is set after the view is created and when I set the data onto the model, the view doesn't update and doesn't read again the model data. This is my ListView: ListViewCountainer.qml Container { // countryModelData is set after ListViewCountainer gets created // when countryModelData gets set, the model is populated with data property variant countryModelData leftPadding: 20.0 rightPadding: 20.0 topPadding: 20.0 bottomPadding: 20.0 CountryDetailsListView { id: countryDetailsListView dataModel: CountryDataModel { countryData: countryModelData } } } And here is my model: countrydatamodel.h #ifndef COUNTRYDATAMODEL_H_ #define COUNTRYDATAMODEL_H_ #include <QtCore/QAbstractListModel> #include <QtCore/QList> #include <QObject> #include <QtCore/QVariant> #include <bb/cascades/DataModel> #include <bb/data/JsonDataAccess> class CountryDataModel : public bb::cascades::DataModel { Q_OBJECT Q_PROPERTY(QVariant countryData READ getCountryData WRITE setCountryData) public: CountryDataModel(QObject* parent = 0); virtual ~CountryDataModel(); Q_INVOKABLE int childCount(const QVariantList& indexPath); Q_INVOKABLE QVariant data(const QVariantList& indexPath); Q_INVOKABLE bool hasChildren(const QVariantList& indexPath); Q_INVOKABLE QString itemType(const QVariantList& indexPath); Q_INVOKABLE void removeItem(const QVariantList& indexPath); Q_INVOKABLE QVariant getCountryData(); Q_INVOKABLE void setCountryData(QVariant data); private: QVariantList m_elements; }; #endif /* COUNTRYDATAMODEL_H_ */ countrydatamodel.cpp #include <src/countrydatamodel.h> #include <QtCore/QtAlgorithms> #include <QtCore/QDebug> #include <bb/cascades/DataModel> #include <bb/data/JsonDataAccess> CountryDataModel::CountryDataModel(QObject* parent) : bb::cascades::DataModel(parent) { } CountryDataModel::~CountryDataModel() { } bool CountryDataModel::hasChildren(const QVariantList &indexPath) { qDebug() << "==== CountryDataModel::hasChildren" << indexPath; if ((indexPath.size() == 0)) { return true; } else { return false; } } int CountryDataModel::childCount(const QVariantList &indexPath) { qDebug() << "==== CountryDataModel::childCount" << indexPath; if (indexPath.size() == 0) { qDebug() << "CountryDataModel::childCount" << m_elements.size(); return m_elements.size(); } qDebug() << "==== CountryDataModel::childCount" << 0; return 0; } QVariant CountryDataModel::data(const QVariantList &indexPath) { qDebug() << "==== CountryDataModel::data" << indexPath; if (indexPath.size() == 1) { return m_elements.at(indexPath.at(0).toInt()); } QVariant v; return v; } QString CountryDataModel::itemType(const QVariantList &indexPath) { Q_UNUSED(indexPath); return ""; } void CountryDataModel::removeItem(const QVariantList& indexPath) { if(indexPath.size() == 1) { m_elements.removeAt(indexPath.at(0).toInt()); } emit itemRemoved(indexPath); } QVariant CountryDataModel::getCountryData() { return QVariant(m_elements); } void CountryDataModel::setCountryData(QVariant data) { m_elements = data.toList(); qDebug() << "================== CountryDataModel: " << m_elements; } I put some debug messages in the childCount function for example and it gets called only once, which means that the ListView asks the model for the data just once, when the model is created. Is it possible to force ListView to read again the data from the model after the model gets populated with data? Or how could I make this approach work and load the data in the view? Thanks!
In order for the model to be updated, the setCountryData member function needs to be updated like so: void CountryDataModel::setCountryData(QVariant data) { m_elements = data.toList(); emit itemsChanged(bb::cascades::DataModelChangeType::AddRemove, QSharedPointer< bb::cascades::DataModel::IndexMapper >(0)); } FML...
You need to declare a signal for the property you want to update in backend. Q_PROPERTY(QVariant countryData READ getCountryData WRITE setCountryData NOTIFY contryDataChanged) add its declaration as well. Then you say - emit contryDataChanged(); wherever you feel like list should re-read contents. (normally setter methods).
System::String^ to TCHAR*
I have a class which collects all paths to .txt files of a given folder and stores them into a vector. Most of the functions I use require the usage of TCHAR* to get/set current directory and so on. The class looks like this: typedef std::basic_string<TCHAR> tstring; class folderManager { private: TCHAR searchTemplate[MAX_PATH]; TCHAR directory[MAX_PATH]; WIN32_FIND_DATA ffd; HANDLE hFind; vector<tstring> folderCatalog; vector<tstring> fileNames; bool succeeded; public: // get/set methods and so on... }; // Changed TCHAR* dir to tstring dir void folderManager::setDirectory(tstring dir) { HANDLE hFind = NULL; succeeded = false; folderCatalog.clear(); fileNames.clear(); // Added .c_str() SetCurrentDirectory(dir.c_str()); GetCurrentDirectoryW(MAX_PATH, directory); TCHAR fullName[MAX_PATH]; StringCchCat(directory, MAX_PATH, L"\\"); StringCchCopy(searchTemplate, MAX_PATH, directory); StringCchCat(searchTemplate, MAX_PATH, L"*.txt"); hFind = FindFirstFile(searchTemplate, &ffd); if (GetLastError() == ERROR_FILE_NOT_FOUND) { FindClose(hFind); return; } do { StringCchCopy(fullName, MAX_PATH, directory); StringCchCat(fullName, MAX_PATH, ffd.cFileName); folderCatalog.push_back(fullName); fileNames.push_back(ffd.cFileName); } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); succeeded = true; } This is where I need to do the conversion of System::String^ to TCHAR* private: System::Void dienuFolderisToolStripMenuItem_Click(System::Object^ sender, System::EventArgs^ e) { FolderBrowserDialog^ dialog; dialog = gcnew System::Windows::Forms::FolderBrowserDialog; System::Windows::Forms::DialogResult result = dialog->ShowDialog(); if (result == System::Windows::Forms::DialogResult::OK) { // Conversion is now working. tstring path = marshal_as<tstring>(dialog->SelectedPath); folder->setDirectory(path); } }
marsha_as "Performs the marshaling on a specific data object to convert it between a managed and a native data type". Here there is the table for possible type conversion. I use it this way: marshal_as<std::wstring>(value) TCHAR can be char or wchar_t, both of them present in marshal_as specialization, I suppose you need to point TCHAR* as template parameter: TCHAR* result = marshal_as<TCHAR*>(value) Actually MSDN says that you have to use it this way: #include <msclr\marshal.h> using namespace System; using namespace msclr::interop; int main(array<System::String ^> ^args) { System::String^ managedString = gcnew System::String("Hello World!!!"); marshal_context ^ context = gcnew marshal_context(); const wchar_t* nativeString = context->marshal_as<const wchar_t*>(managedString); //use nativeString delete context; return 0; }
How do I make an interprocess rwlock in FreeBSD?
What is the way to make an interprocess read-write lock in FreeBSD? I'm looking for something like pthread's rwlock that could be set to be shared between processes by "pthread_rwlockattr_setpshared" and PTHREAD_PROCESS_SHARED flag which successfully worked in Linux. But FreeBSD doesn't support this flag. Thank you in advance.
Found a simple and portable solution built on posix semaphores here: http://stupefydeveloper.blogspot.com/2009/03/nix-rw-lock-with-semaphores.html #include <semaphore.h> #include <errno.h> struct rwlock { sem_t rlock; sem_t wlock; }; void init_rwlock(struct rwlock *rw) { sem_init(&rw->rlock, 1, 0); sem_init(&rw->wlock, 1, 1); } void destroy_rwlock(struct rwlock *rw) { wlock(rw); sem_destroy(&rw->rlock); sem_destroy(&rw->wlock); } void rlock(struct rwlock *rw){ sem_wait(&rw->wlock); sem_post(&rw->rlock); sem_post(&rw->wlock); } void wlock(struct rwlock *rw) { int readers = 0; sem_wait(&rw->wlock); do { if (sem_getvalue(&rw->rlock, &readers) != -1) { if (readers == 0) break; } usleep(1); } while (1); } void runlock(struct rwlock *rw) { do { if (sem_trywait(&rw->rlock) == -1) { if (errno != EAGAIN) continue; } break; } while (1); } void wunlock(struct rwlock *rw) { sem_post(&rw->wlock); }