CreateThread passing std::string as argument - c++

I need to create a thread in a managed C++ code (CLR) to call an unmanaged C++ class member function passing a std::string as a parameter. The thread is being called, but the received std::string is being received as an empty string:
The managed code:
std::string param;
CreateThread(0, NULL, (LPTHREAD_START_ROUTINE) &MyThread.Start, &MyThread, (DWORD) &param, NULL);
The unmanaged code:
class MyThread
{
public:
MyThread();
static void Start(std::string &param);
};
void MyThread::Start(std::string &param)
{
std::cout << param << std::endl; <<=== param is empty here
}

Specifically in your case, you're passing &MyThread as the thread function parameter and passing the param as the dwCreationFlags parameter of the CreateThread function, which specifies thread creation options.
Additionally, you'll need to make sure you keep param around for the lifetime of the thread.
Hope that helps.

Related

How to pass in the 'this' pointer to a C++ WinAPI thread?

I am trying to run a C++ thread but also pass in the instance to the class itself. I cannot seem to figure it out.
I have a struct for parameters to the thread:
struct CLASS_PARAMS {
SomeClass* ptr;
};
I then call my setup method:
void SomeClass::setup() {
CLASS_PARAMS params;
params.ptr = this;
CreateThread(NULL, 0, SetupThread, &params, 0, NULL);
}
and right above SomeClass::setup(), I define SetupThread:
DWORD WINAPI SetupThread(LPVOID lpParam) {
CLASS_PARAMS* params = (CLASS_PARAMS *) lpParam;
SomeClass* inst = params->ptr;
....
....
}
However, I get read-access violations on using inst. I have other methods in SomeClass that I need to access via the thread:
inst->getSomeValue();
...
inst->setSomeValue(someValue);
...
but it will not allow me. Any suggestions on what I'm doing wrong?
You allocate CLASS_PARAMS on stack, so it is destroyed before used.
Allocate it dynamically, pass pointer and free it in the thread.
Alternatively, if you need to pass only this, pass it without wrapping structure, just cast to LPVOID and back (but be sure to use the same class pointer type to avoid pointer adjustment bugs)

How can I begin thread in windows using functor as thread function without using C++11 thread?

I'm writing a simple thread lib for Windows. I want to pass this functor
struct callable
{
void operator()()
{
for(int i = 0; ;++i)
{
std::cout << i << std::endl;
}
}
};
In _beginthread() this way:
int main()
{
callable c;
_beginthread(c, 0, 0);
}
but it's not possible. The ability to pass functor in the thread is very necessary for my library. I know that boost::thread provides this ability, thus it is possible. How can I begin thread in windows using functor as thread function without using C++11 thread?
[upd] without using C++11 thread
The standard technique is as follows:
Define a struct to hold whatever information you need to pass to the thread. In your case that information is the callable functor. So, you already have a suitable struct at hand.
Allocate one of these structs on the heap. This happens in the calling thread, but the information is passed to the created thread which is why it cannot live on the stack.
Call CreateThread passing a suitable thread proc (more later), and the address of your struct in the lpParameter parameter.
In the thread proc, you are passed the address of the struct in lpParameter.
Cast that pointer to the appropriate type and call your functor.
Delete the heap allocated memory.
The thread proc looks like this:
DWORD WINAPI ThreadProc(void *lpParameter)
{
callable *c = (callable*)lpParameter;
(*c)();
delete c;
return 0;
}
And the call to CreateThread is along these lines:
callable *c = new callable;
// initialise c
CreateThread(NULL, 0, ThreadProc, (void*)c, 0, &threadID);
I apologise if there are syntax errors here, I'm not at all fluent in C++.

Create thread within DLL

I'm working on a .NET profiler which I'm writing in c++ (a dll that uses ATL). I want to create a thread that writes into a file every 30 seconds. I want the thread function to be a method of one of my classes
DWORD WINAPI CProfiler::MyThreadFunction( void* pContext )
{
//Instructions that manipulate attributes from my class;
}
when I try to start the thread
HANDLE l_handle = CreateThread( NULL, 0, MyThreadFunction, NULL, 0L, NULL );
I got this error :
argument of type "DWORD (__stdcall CProfiler::*)(void *pContext)"
is incompatible with parameter of type "LPTHREAD_START_ROUTINE"
How to properly create a thread within a DLL?
Any help would be apreciated.
You cannot pass a pointer to a member function as if it were a regular function pointer. You need to declare your member function as static. If you need to call the member function on an object you can use a proxy function.
struct Foo
{
virtual int Function();
static DWORD WINAPI MyThreadFunction( void* pContext )
{
Foo *foo = static_cast<Foo*>(pContext);
return foo->Function();
}
};
Foo *foo = new Foo();
// call Foo::MyThreadFunction to start the thread
// Pass `foo` as the startup parameter of the thread function
CreateThread( NULL, 0, Foo::MyThreadFunction, foo, 0L, NULL );

Defining function inside function call

I had an idea to save time involving creating a temporary function to use as an argument to a function that needs it. The reason I'm after this behaviour is to do things in a new thread in an easy manner (using Win32 API) without having to define all kinds of functions I'll use.
Here's an example:
void msg (const string & message) {
MessageBox (0, message.c_str(), "Message", 0);
}
This will produce a message box, but your program is halted until it closes. The solution is to create a thread for the message box that runs concurrently with the main thread.
void msg (const string & message) {
CreateThread (0, 0,
(LPTHREAD_START_ROUTINE)({MessageBox (0, message.c_str(), "Message", 0);}),
0, 0, 0);
}
In this case, LPTHREAD_START_ROUTINE is defined as
typedef DWORD (*LPTHREAD_START_ROUTINE)(LPVOID param);
Since I have multiple functions wanting another thread for a purpose like that, putting the function in the call to CreateThread seems to be working well.
But say I wanted to use that LPVOID param. I'd like to know how standard this method is, and where I can find out how to use it for more advanced techniques. Also, I know using it in a function that will store it for later use (eg. a message loop function where you can add messages to handle and a corresponding function to call) is a bad idea as the function is temporary and would not be able to be called when needed. Is there really any use beyond things like threads where it's annoying to make one line functions elsewhere in order to use it?
It's called a "lambda". They are very useful for many purposes beyond this and are in the C++11 Standard. You can find them in the latest GCC and MSVC. However, MSVC's current implementation does not permit conversion to a function pointer, as the Standard did not specify such a conversion at that time. VC11 will implement this conversion. This code is Standard-conforming C++11:
void msg (const string & message) {
CreateThread (0, 0,
[](LPVOID* param) { MessageBox (0, message.c_str(), "Message", 0); },
0, 0, 0);
}
There was another way in times lambdas were not the standard - you could define function-local class and define the inner function within that class. Something like:
void msg(const string &message)
{
struct message_box
{
static DWORD WINAPI display(LPVOID param)
{
/// do the action
return 0;
}
};
::CreateThread(0, 0,
&message_box::display,
0, 0, 0);
}
Now lets consider your question. You wanted to pass the message text in STL's std::string. Since it occupies dynamic memory which can be freed by your initial thread, the new thread, running in parallel, must have guarantee, that the message text will still be available to it. This can be done by copying (which would work with lambda's by-value capture - [=] introducer) or sharing a reference (via reference counting, let'd say). Lets consider copying:
void msg(const string &message)
{
struct message_box
{
static DWORD WINAPI display(void *param)
{
MessageBox(0, ((string *)param)->c_str(), "Message", 0);
delete (string *)param;
return 0;
}
};
string *clone = new string(message);
::CreateThread(0, 0,
&message_box::display,
clone, 0, 0);
}
Please, note, that the copy is allocated in the initial thread and destroyed in the new one. This requires multithreading support from your CRT.
In the case new thread fails to start, you'll end up with memory being orphaned. Lets fix this:
void msg(const string &message)
{
struct message_box
{
static DWORD WINAPI display(void *param)
{
auto_ptr<string> message((string *)param);
MessageBox(0, message->c_str(), "Message", 0);
return 0;
}
};
auto_ptr<string> clone(new string(message));
if (::CreateThread(0, 0, &message_box::display, clone.get(), 0, 0))
clone.release(); // release only if the new thread starts successfully.
}
Since the memory is being managed by the CRT, the CRT have to be initialized in the new thread, which is not done by CreateThread API. You have to use CRT beginthread/beginthreadex instead:
void msg(const string &message)
{
struct message_box
{
static unsigned int WINAPI display(void *param)
{
auto_ptr<string> message((string *)param);
MessageBox(0, message->c_str(), "Message", 0);
return 0;
}
};
auto_ptr<string> clone(new string(message));
if (_beginthreadex(0, 0, &message_box::display, clone.get(), 0, 0))
clone.release(); // release only if the new thread starts successfully.
}
This solution leaves aside the problem of the thread itself being leaked as a resource. But, I believe you may find another posts for this on stackoverflow.com :)
thanks )

How do i call worker thread in a same class (C++, MFC)?

Here is my code which contains error:
void ClassA::init()
{
HANDLE hThread;
data thread; // "thread" is an object of struct data
hThread = CreateThread(NULL, 0, C1::threadfn, &thread, 0, NULL);
}
DWORD WINAPI ClassA::threadfn(LPVOID lpParam)
{
data *lpData = (data*)lpParam;
}
Error:
error C3867: 'ClassA::threadfn': function call missing argument list; use '&ClassA::threadfn' to create a pointer to member
What is the proper way to make the worker thread working in a single class?
The thread creation functions are not aware of C++ classes; as such, your thread entry point must be either a static class member function, or a non-member function. You can pass in the this pointer as the lpvThreadParam parameter to the CreateThread() function, then have the static or non-member entry point function simply call the threadfn() function via that pointer.
If the threadfn() function is static, then make sure you put & before C1::threadfn.
Here's a simple example:
class MyClass {
private:
static DWORD WINAPI trampoline(LPVOID pSelf);
DWORD threadBody();
public:
HANDLE startThread();
}
DWORD WINAPI MyClass::trampoline(LPVOID pSelf) {
return ((MyClass)pSelf)->threadBody();
}
DWORD MyClass::threadBody() {
// Do the actual work here
}
HANDLE MyClass::startThread() {
return CreateThread(NULL, 0, &MyClass::trampoline, (LPVOID)this, 0, NULL);
}
You're using MFC, according to the tags. CreateThread is the Win32 C API, you should look at CWinThread instead.
Follow the advice in the warning error, then this should work provided the member function threadfn is static.
What happens if you do what the error says?
CreateThread(NULL, 0, &C1::threadfn, &thread, 0, NULL); // now passing pointer
This assumes that threadfn() is static.