I have CPrinterDlg class which contains
// CPrinterDlg.h
public:
CEdit m_editRxFreq;
void print_SignalData(unsigned int freq, float wvlen);
// CPrinterDlg.cpp
void CPrinterDlg::print_SignalData(unsigned int freq, float wvlen)
{
m_editRxFreq.SetWindowTextW(L"ddd");
}
In order to access that function I did in MainFrm like this:
public:
CPrinterDlg m_PrinterDlg;
CPrinterDlg& getPrinterDlg() { return m_PrinterDlg; }
And from where I am calling print_SignalData(...) is CSMsg``` class
void CSockMsg::Send_SignalData(unsigned char* msg)
{
//..
CMainFrame* pMain = (CMainFrame*)AfxGetApp()->GetMainWnd();
pMain->getPrinterDlg().print_SignalData(freq, wvlen);
}
When I call print_SignalData(...) from one of the CPrinter function directly, it's working well. But, When I try to call it from CSMsg::Send_SignalData(unsigned char* msg) it's giving me Debug Assertion(...MFC\winocc.cpp Line: 242) from this point:m_editRxFreq.SetWindowTextW(L"ddd");.
And I see that m_editRxFreq is NULL.
So, how do you think why m_editRxFreq is getting be NULL? and how can I solve this problem??
Solved!
I was doing
public:
CPrinterDlg m_PrinterDlg;
CPrinterDlg& getPrinterDlg() { return m_PrinterDlg; }
in CMainFrm.h,
and actually Creating and Showing that dlg
CPrinterDlg dlg;
dlg.Create(...);
dlg.ShowWindow(...);
was in CxxView::OnInitialUpdate().
That's why when I called pMain->getPrinterDlg().print_SignalData(freq, wvlen); it was giving me NULL;
So in order to solve it,
I created CPrinterDlg dlg.Create(...) in CMainFrm class but not in CxxxView class.
Related
I'm trying to create a dynamic VCL control at runtime and assign an event handler to it.
I think I've tried everything to get this to work, but cannot (everything I try generates different errors).
If you could help fill in the question marks in the code below, it would be of great help!
Oh, in case you're wondering why it's in a namespace instead of a class, it's because this is actually a large library that I just kept adding to. When I change it to a class, you'd think it would be fine, but no, it generates a gazillion weird errors.
test.h
namespace TestSpace {
TTimer *time;
AnsiString file;
void __fastcall MyFunc(AnsiString f);
?Declaration for OnTimer event?
}
test.cpp
void __fastcall TestSpace::MyFunc(AnsiString f) {
TestSpace::file = f;
TestSpace::time->OnTimer = ?;
TestSpace::time->Enabled = true;
}
TestSpace::?(TObject* Sender) {
TestSpace::time->Enabled = false;
DeleteFile(TestSpace::file);
}
A VCL event handler is expected to be a non-static member of a class. Your OnTimer handler is not a class member, it is a free-floating function instead (the namespace is not important).
The correct way to solve this issue is to create a class for your OnTimer event handler, and then instantiate that class alongside the TTimer, eg:
test.h
namespace TestSpace {
class TimerEvents {
public:
void __fastcall TimerElapsed(TObject *Sender);
};
TTimer *time;
TimerEvents time_events;
AnsiString file;
void __fastcall MyFunc(AnsiString f);
}
test.cpp
void __fastcall TestSpace::MyFunc(AnsiString f) {
TestSpace::file = f;
TestSpace::time->OnTimer = &(time_events.TimerElapsed);
TestSpace::time->Enabled = true;
}
void __fastcall TestSpace::TimerEvents::TimerElapsed(TObject* Sender) {
// 'this' is the TimerEvents object
// 'Sender' is the TTimer object
TestSpace::time->Enabled = false;
DeleteFile(TestSpace::file);
}
That being said, there is actually an alternative way to use a free-floating function as a VCL event handler like you want, by using the System::TMethod struct:
test.h
namespace TestSpace {
TTimer *time;
AnsiString file;
void __fastcall MyFunc(AnsiString f);
// NOTE: must add an explicit void* parameter to receive
// what is supposed to be a class 'this' pointer...
void __fastcall TimerElapsed(void *This, TObject *Sender);
}
test.cpp
void __fastcall TestSpace::MyFunc(AnsiString f) {
TestSpace::file = f;
TMethod m;
m.Data = ...; // whatever you want to pass to the 'This' parameter, even null...
m.Code = &TestSpace::TimerElapsed;
TestSpace::time->OnTimer = reinterpret_cast<TNotifyEvent&>(m);
TestSpace::time->Enabled = true;
}
void __fastcall TestSpace::TimerElapsed(void *This, TObject* Sender) {
// 'This' is whatever you assigned to TMethod::Data
// 'Sender' is the TTimer object
TestSpace::time->Enabled = false;
DeleteFile(TestSpace::file);
}
I am trying to pass this pointer as an argument to my callback(), but it seems like the behaviour is not same as I expect.
I am trying to pass the caller object as my user_data (i.e. 2nd argument of callback() ), apparently it fails!
Within SaveSettings() method, if I type cast void*)obj to (SettingsGui*), and call foo(), it behaves as expected (so, I am able to pass a pointer to calling SettingsGui obj?), but when I try to access vector<string> Order (which is filled with string objects within SettingsGui::Show() method), it fails.
Is my assumption of "successfully passing a pointer to calling SettingsGui object" wrong? If so, why and how can I fix it?
// Gui for Application Settings
class SettingsGui {
vector<string> Order;
public:
const char foo() { return "Test"; }
void Show() {
...
Order.size(); /* it is 44 here */
...
// Save Button
Fl_Button *SaveButton = new Fl_Button(...);
SaveButton->callback(SaveSettings, this);
...
}
static void SaveSettings(Fl_Widget *w, void *d){
SettingsGui *T = (SettingsGui*)obj;
fl_alert(T->foo()); /* this works */
char buf[32];
fl_alert(itoa(T->Order.size(),buf,10)); /* return -1 */
}
};
// Main Application Window
class MainApp {
public:
void Show(){
...
...
Fl_Button *flButton_settings = new Fl_Button(...);
flButton_settings->callback(OpenSettingsGui);
}
static void OpenSettingsGui (Fl_Widget *w, void *d) {
SettingsGui p;
p.ReadSettings(...);
p.Show();
}
};
T->foo() works because it doesn't access anything within the class
T->Order.size() doesn't work because T is being cast to obj. It should be cast to d.
static void SaveSettings(Fl_Widget *w, void *d){
SettingsGui *T = (SettingsGui*)d;
I got a unhandled exception error at runtime when using the following C++ code, you can follow the error with debug using Visual Studio. Why will this exception happen, can you explain it?
First I define a class with a menber variable "_name"
void insert_Fenster(int pos,wstring name);
wstring get_Fenster_name(int pos);
class Fenster
{
public:
Fenster(wstring name)
:_name(name)
{}
void reload()
{
_name;
insert_Fenster(1,L"temp");
wstring tmp = get_Fenster_name(1);
_name = tmp; //ERROR!!!
}
wstring get_name()
{
return _name;
}
private:
wstring _name;
};
Second I define a class to hold a map of the class
class FensterManager
{
public:
bool has(int pos)
{
if (_mapFenster.find(pos)!=_mapFenster.end())
return true;
else
return false;
}
void insert(int pos,wstring name)
{
if (has(pos))
{
_mapFenster.erase(pos);
}
_mapFenster.insert(make_pair(pos,Fenster(name)));
}
Fenster& get_Fenster(int pos)
{
return _mapFenster.at(pos);
}
private:
static map<int,Fenster> _mapFenster;
};
And some util functions
void insert_Fenster(int pos,wstring name)
{
FensterManager fm;
fm.insert(pos,name);
}
void reload_Fenster(int pos)
{
FensterManager fm;
if (fm.has(pos))
fm.get_Fenster(pos).reload();
}
wstring get_Fenster_name(int pos)
{
wstring name;
FensterManager fm;
if (fm.has(pos))
name = fm.get_Fenster(pos).get_name();
return name;
}
//Init of static member before main function
map<int,Fenster> FensterManager::_mapFenster;
that is the main function
void main()
{
insert_Fenster(1,L"xyz");
reload_Fenster(1);
}
The exception happen at "reload" function in class "Fenster".
With error message:
Unhandled exception at 0x005cca34 (msvcr100d.dll) in Regular_Expression.exe: 0xC0000005: Access violation writing location 0xfeeefeee.
When you call reload_Fenster(1);, it will call Fenster::reload. In that function you call insert_Fenster(1,L"temp");. FensterManager::insert will first erase position 1 from the map. So when you return to Fenster::reload, the instance has been deleted. As soon as you try to access _name, you try to access memory which has been deleted.
edit:
To clarify; this function call:
fm.get_Fenster(pos).reload();
will first call fm.get_Fenster(pos) and then call reload() on the result. If fm.get_Fenster(pos) changes in the reload() function, execution will not move the new Fenster, but the old one will keep executing. Even if you delete the old Fenster.
You should make sure not to delete an instance if you are still running functions inside it. It will crash the application as soon as you try to access members, because they are stored in memory which has been deleted.
looks like something inside void insert_Fenster(int pos,wstring name); - look further up the call stack and you'll see which part of your code is calling into the runtime dll. That'll be the error.
Can you please provide more information regarding the unhandled exception.
There is one obvious mistake in the above code. The insert_Fenster is inserting into a FensterManager instance and the reload_Fenster is trying to reload from a different instance of the FensterManager which is wrong.
void main()
{
FensterManager fm;
insert_Fenster(fm, 1,L"xyz");
reload_Fenster(fm, 1);
}
The insert and reload method should be updated as follows:
void insert_Fenster(FensterManager &fm, int pos,wstring name)
{
fm.insert(pos,name);
}
void reload_Fenster(FensterManager &fm, int pos)
{
if (fm.has(pos))
fm.get_Fenster(pos).reload();
}
I try to implement an array of function pointers in an singleton owning a thread.
In the thread function I get an error, telling me that a member has to be relative to an object. More in the commentline...
Header:
typedef struct{
int action;
HWND handle;
}JOB;
class Class{
public:
enum Action { 1,2 };
private:
JOB m_currentJob;
queue<JOB> Jobs;
static DWORD WINAPI ThreadFunction(LPVOID lpParam);
void (Class::*ftnptr[2])(JOB Job);
void Class::ftn1(JOB Job);
void Class::ftn2(JOB Job);
// Singleton pattern
public:
static Class* getInstance(){
if(sInstance == NULL)
sInstance = new Class();
return sInstance;
}
private:
Class(void);
~Class(void);
static Class* sInstance;
};
Body:
#include "Class.h"
Class* Class::sInstance = NULL;
Class::Class(){
this->ftnptr[0] = &Class::ftn1;
this->ftnptr[1] = &Class::ftn2;
}
DWORD WINAPI Class::AutoplayerThreadFunction(LPVOID lpParam)
{
Class *pParent = static_cast<Class*>(lpParam);
while(true){
(pParent->*ftnptr[pParent->m_currentJob.action])(pParent->m_currentJob);
/* The line above causes the compiler error. Curious to me is that
* neither "pParent->m_currentJob" nor "pParent->m_currentJob" cause
* any problems, although they are members too like the ftnptr array.
*/
}
}
void Class::ftn1(JOB Job){}
void Class::ftn2(JOB Job){}
A call via getInstance from the SingletonPattern doesnt make it any better.
Any suggestions?
ftnptr is a member of Class. However, you access it directly. That is, pParent->*ftnptr[...] means "access the member of pParent designated by the pointer ftnptr[...]", but it doesn't imply that ftnptr too is a member of pParent.
The correct code is (pParent->*(pParent->ftnptr[...]))(...). But I would recommend extracting the array index expression from that:
auto fnptr = pParent->ftnptr[...];
(pParent->*fnptr)(...);
I think it might be how you declare your array of pointer-to-member-functions. (Edit: This wasn't what was wrong. I'm keeping this answer up anyway, because typedefs for function pointers can really make code cleaner, so I think this is good advice.)
Try using a typedef:
typedef void (Class::*ftnptr)(JOB Job);
ftnptr[2] fn_ptrs;
Then use it like so:
Class::Class(){
this->fn_ptrs[0] = &Class::ftn1;
this->fn_ptrs[1] = &Class::ftn2;
}
DWORD WINAPI Class::AutoplayerThreadFunction(LPVOID lpParam)
{
Class *pParent = static_cast<Class*>(lpParam);
while(true){
(pParent->*(pParent->fn_ptrs[pParent->m_currentJob.action]))(pParent->m_currentJob);
/* The line above causes the compiler error. Curious to me is that
* neither "pParent->m_currentJob" nor "pParent->m_currentJob" cause
* any problems, although they are members too like the ftnptr array.
*/
}
}
class IEngine: public ICoreObject
{
private:
Network *_Network;
bool _Process;
public:
IEngine();
~IEngine();
void Initial(...);
void StartServer(unsigned short port);
bool Process();
void StopProcess();
void StartProcess();
friend void ShellCode(int id,struct NE_Bin var);
};
Why i cant use _Network from ShellCode ?
this is definition of ShellCode function
void ShellCode(int id,struct NE_Bin var) //функция-друг
{
std::cout<<"ShellFunc Delegated"<<std::endl;
var.data = (void *)"T";
var.length = 1;
//_Network->SendMessageW(id, var);
}
Im trying to get to the _Network class and i get errors.
IEngine has ShellCode as a friend. That means you can access private **members of an IEngine object. _Network is just a variable in your context, not bound to anything.
Something like this would work:
void ShellCode(int id,struct NE_Bin var, IEngine* pEngine)
{
std::cout<<"ShellFunc Delegated"<<std::endl;
var.data = (void *)"T";
var.length = 1;
pEngine->_Network->SendMessageW(id, var);
}
but you need to pass the IEngine as parameter:
IEngine* pEngine /*initialize it here*/;
ShellCode(0, NE_Bin(), pEngine);
or you can use a global instance inside the method (if you have one).
Well you'd need an instance of of IEngine as a parameter to access it's member variable...