Create thread within DLL - c++

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 );

Related

How can i implement CreateThread - LPTHREAD_START_ROUTINE type ThreadProc callback function inside a C++ Class

Happy new year!
This is my baby steps in C++ world.
I used an example from learn.microsoft.com to create an example Win32 Console project which uses the WaitForMultipleObjects function to persist until all worker threads have terminated. All worked great!
Things get complicated (argument of type DWORD (Thread::*)(LPVOID lpParam) is incompatible with parameter of type "LPTHREAD_START_ROUTINE")
when i start to try to port the functionality of the concept inside a class which is similar like this:
class Threads
{
private:
HANDLE comThreads[1];
DWORD WINAPI closeThreadProc(LPVOID lpParam)
{
// lpParam not used in this example.
UNREFERENCED_PARAMETER(lpParam);
printf("Thread %d exiting\n", GetCurrentThreadId());
return 1;
}
BOOL CreateThreads(void)
{
DWORD dwThreadID;
comThreads[0] = CreateThread(
NULL, // default security
0, // default stack size
closeThreadProc, // Close thread function
NULL, // no thread parameters
0, // default startup flags
&dwThreadID);
}
public:
void Init()
{
CreateThreads();
}
}
I will try to use this class to create a Dynamic-link library(DLL).
While i am searching the answer to my own question.
I would like to ask you:
Is this even possible?
If it is possible. How can i achieve this, without loosing the underlying concept?
Thank you!
Edit:
Sorry for forgetting to tell if is it possible to make this, without making DWORD WINAPI closeThreadProc(LPVOID lpParam) static!
I did try to make it static before i posted the Question and things became even more wild (I barely forced to make everything in the class static).
I think this is the C++'s way to punish a rookie.
The LPVOID argument is there for a reason. The trick is to make the callback a static member but pass this as the extra parameter. You can then cast the LPVOID argument back to your object and call the method you want to. Some code will make it clearer
static DWORD WINAPI closeThreadProcCallback(LPVOID lpParam)
{
return static_cast<Threads*>(lpParam)->closeThreadProc();
}
BOOL CreateThreads(void)
{
DWORD dwThreadID;
comThreads[0] = CreateThread(
NULL, // default security
0, // default stack size
closeThreadProcCallback, // Close thread callback function
this, // this object is the thread parameter
0, // default startup flags
&dwThreadID);
}
EDIT added WINAPI as suggested by Tomer W.
a threadStartfunction cant be _thiscall, and have to be _stdcall,
therefore i'd declare a static private method to pass your call to your object, i use the lpParameter to pass the object to the static function.
class Threads
{
private:
HANDLE comThreads[1];
static DWORD WINAPI staticThreadProc(LPVOID lpParam)
{
Threads& callingThread = *reinterpret_cast<Threads*>(lpParam);
return callingThread.closeThreadProc();
}
DWORD closeThreadProc()
{
printf("Thread %d exiting\n", GetCurrentThreadId());
return 1;
}
BOOL CreateThreads(void)
{
DWORD dwThreadID;
comThreads[0] = CreateThread(
NULL, // default security
0, // default stack size
staticThreadProc, // Close thread function
this, // no thread parameters
0, // default startup flags
&dwThreadID);
}
public:
void Init()
{
CreateThreads();
}
}

CreateThread passing std::string as argument

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.

Thread in C++ DLL called by EPrime causes exception

I have a DLL written in C++, which exports a function that calls a thread. If the function returns before the thread terminates (which is the standard usecase), EStudio crashes. My platform is Windows 10, 64 bits, but the DLL is compiled in x86 mode.
The function is thus declared in EPrime:
Declare Function moop stdcall Lib "meep.dll" () As Long
Dim oPtr As Long
oPtr = moop()
and the DLL code looks like this:
void* event_loop_func(void* eye_tracker)
{
Sleep(3000);
return 0;
}
void * __stdcall moop()
{
void * hThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
(LPTHREAD_START_ROUTINE)event_loop_func, // thread function name
NULL, // argument to thread function
0, // use default creation flags
NULL);
return 0;
}
Any advice on how to run a thread from the DLL without crashing EStudio?

Create new thread in class (windows)

I want to create a new thread in a class. The problem is when I need to pass a pointer to the function that will be used in the new thread. I am unable to pass a pointer to the function. A class function under the hood is basically this right?
void foo (this);
Then why does this code refuse to compile?
class TimeClass
{
private:
DWORD dwThreadId;
HANDLE hThread;
LPTHREAD_START_ROUTINE Timer ();
public:
TimeClass ();
};
TimeClass::TimeClass ()
{
dwThreadId = CreateThread (NULL, 0, Timer, this, 0, &dwThreadId);
}
The signature of a thread function must be
DWORD WINAPI ThreadProc(LPVOID param);
An ordinary (i.e. nonstatic) C++ member function does not have the WINAPI calling convention so it cannot be used as a thread function. If you declare the member function as static then it can be used as a thread function:
static DWORD WINAPI ThreadProc(LPVOID param);
A class function under the hood is basically this right?
void foo (this);
Generally, no. It is what the compiler decides it to be, and there may be all kinds of 'non-virtual thunks', inlines, etc. The compiler is allowed to optimize the program in any way that doesn't change the program's behaviour, and such implementation details are not defined by the standard. That's why what you're trying to do is UB, and your best bet here (IMHO) would be something like:
extern "C" wrapper(void * p)
{
static_cast<TimeClass*>(p)->whatever();
}
The ThreadProc() prototype is
DWORD WINAPI ThreadProc(
_In_ LPVOID lpParameter
);
So you need to change the Timer() declaration like:
DWORD WINAPI Timer()

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.