0

I wanted to show a problem I’m having while invoking functions of an instantiated class in C++.

I’m using a separate thread to listen to a TCP socket, so when data comes, I want to call a function to start doing tasks. I’m using process.h library and _beginthread(socket_init,0,NULL); to start the thread with socket_init() function, which starts the listener.

To put you into situation, right before the thread initialization call, I have this:

CPhoneDlg dlg = new CPhoneDlg;
m_pMainWnd = &dlg;

This class has this function declared:

CTapiLine* CPhoneDlg::GetActiveLine()   {...}

So the point of all this, is to be able to call GetActiveLine() from the function that is being executed in the separate thread.

For that I tried to do this:

CTapiLine* line = dlg.GetActiveLine();

But it just doesn’t know what dlg is, showing "identifier not declared" when I try to compile the code.

Is there any way to make dlg object visible so its methods become "invokable" by the separate thread?

Toby Speight
  • 27,591
  • 48
  • 66
  • 103

1 Answers1

0

I had to figure out almost this exact issue just the other day, so I think I can help. You need to pass an object to your class into the thread function. See the following code:

DWORD WINAPI PhoneThread(LPVOID lpParam)
{
    CPhoneDlg *phoneDlg = reinterpret_cast<CPhoneDlg *>(lpParam);
    CTapiLine* line = phoneDlg.GetActiveLine();
}

And instantiate the thread like this (from within your class!):

CreateThread(NULL, 0, PhoneThread, this, 0, NULL);

As long as GetActiveLine() is public, you should be able to make it work like this.

What I am doing is passing in a pointer to the main class as an LPVOID. When you get into the thread, you can use reinterpret_cast to cast it back to the type of the main class. Now, you have a pointer to the class from within your thread and you can access public functions and variables.

C. Korb
  • 287
  • 1
  • 10
  • This sounds like a good way to make it. I'll be trying this as soon as I get to work on monday. I'll get back with whatever I come across! Thanks C. Korb for the explanation, it is crystal clear. – Ignacio Serna Apr 29 '16 at 14:02
  • And sorry, for some reason I was thinking you were using winapi, which you may not be. There are plenty of other ways to do what you are trying, but this is a really simple way to get it done. – C. Korb Apr 29 '16 at 14:06
  • Another way (if you want), is you could declare a global variable: `CPhoneDlg *g_phonDlgPtr`. In your constructor for CPhoneDlg, set `g_phoneDlgPtr = this` and now you can use `g_phoneDlgPtr` anywhere to access that class. This is a much more powerful and dangerous solution however, so I would stick to the above solution if it works for you. – C. Korb Apr 29 '16 at 14:10
  • Alright I'll try to explain the problem I'm facing now. I solved the problem by creating a global pointer for the dialog, then calling functions from within that pointer. Here's when the problem comes, I can call a method (lets say, Set_EditBox) and it's supposed to write something into the dialog's editbox, but calling it from the secondary thread seems to do nothing actually. As well as it crashes if I try to launch a call (OnMakeCall method on the dialog class) from the secondary thread. I tried to put a barrier on the main thread, but I cant afford it to stay frozen. – Ignacio Serna May 02 '16 at 10:37
  • Can you share a little more of the code? It's difficult to understand the problem without it. – C. Korb May 02 '16 at 11:14
  • Alright, Ill try to point out the fragments of the code involved. First, as global variable I've declared "CPhoneDlg *dlg;". Then on the instance of the MainApp I declare the dialog like this: "BOOL CMainApp::InitInstance() {dlg = new CPhoneDlg; m_pMainWnd = dlg; _beginthread(socket_init,0,NULL); ... } Then socket_init, which is on a separate thread, wants to call "dlg->set_m_strNumber();", this method just changes the value of an editBox. The code of this last method is alright, since if I call it from within the main thread, it works. Thank you C. Korb for keeping up with me. – Ignacio Serna May 02 '16 at 11:21
  • So when does socket_init call set_m_strNumber? Timing is important especially with threads. It's possible that the thread actually is setting that value but the main thread is overwriting it, especially since it looks like the thread is being started within an "init" function. – C. Korb May 02 '16 at 11:32
  • The call is made when I recieve something from the socket via javascript tcp sockets. That is, when I launch the script with nodejs. I usually wait for a while before launching the script, so the editbox must be already declared and initialized, I dont think it's a matter of it being overwritten. More like I think it's something about the dialog not "existing" in the secondary thread. I dont get this last thing since its declared as a global variable. Furthermore if I try to launch a call (another method) it just breaks with "Debug Assertion Failed" error. Something about wincore.cpp. – Ignacio Serna May 02 '16 at 11:36
  • It's pretty hard to help without knowing or seeing more of the source code. Here are some links that may assist: [debug assertion](http://stackoverflow.com/questions/30757006/mfc-settitle-causing-weird-debug-assertion), [Mfc multi threading](https://support.microsoft.com/en-us/kb/147578) – C. Korb May 02 '16 at 13:20