-2

I'm studying threads in c++. I'm using the CreateThread() function from windows.h library:

#include <windows.h>
#include <iostream>
#include <unistd.h>


DWORD WINAPI ThreadFunc(void* data, std::string message) {
    std::cout<<message;
  return 0;
}

int main() {
  std::string saluti="hi";
  HANDLE thread = CreateThread(NULL, 0, ThreadFunc, &saluti, 0, NULL);
  sleep(5);
  
}

The error:

 error: invalid conversion from 'DWORD (__attribute__((__stdcall__)) *)(void*, std::__cxx11::string) {aka long unsigned int (__attribute__((__stdcall__)) *)(void*, std::__cxx11::basic_string<char>)}' to 'LPTHREAD_START_ROUTINE {aka long unsigned int (__attribute__((__stdcall__)) *)(void*)}' [-fpermissive]
   HANDLE thread = CreateThread(NULL, 0, ThreadFunc, &saluti, 0, NULL);
                                                                     ^

how can i pass a std::string to a thread function?

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
vik
  • 19
  • 2
  • 1
    You pass it in as the `data` parameter. The hard part is ensuring that the given `string` lives long enough for the thread to use it. – user4581301 May 03 '22 at 19:02
  • Helpful documentation: [ThreadProc callback function](https://learn.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms686736(v=vs.85)) The function you provide must look exactly like what the documentation says. Do not try to force it with a cast. – user4581301 May 03 '22 at 19:03
  • Unrelated, what magical runtime set grants you the glories of `` on Windows ? Regardless, unless you're set on living in a pure windows-thread world, consider yourself fortunate `` is viable now as part of the C++ standard library and use that; native windows threads a PITA in comparison. – WhozCraig May 03 '22 at 19:04
  • Probably because the question is asked and answered regularly as well as being [well documented](https://learn.microsoft.com/en-us/windows/win32/procthread/creating-threads) – user4581301 May 03 '22 at 19:08
  • @WhozCraig not so easy dude, most of compilers don't support threads yet on Windows and don't talk about that stupid flags as -lpthread or -std=c++11 because they don't work. I'm aware of the existance of `std::thread` but as previously said, it's not supported by the compiler i need to use. – vik May 03 '22 at 19:10
  • Most OLD compilers. I haven't had a problem with finding `std::thread` support in a toolchain including GCC6.3 (11.3 was recently released) or better in the last 6-7 years. [Here's installation instructions for a good, up-to-date tool chain](https://stackoverflow.com/questions/30069830/how-to-install-mingw-w64-and-msys2) for Windows that includes a package manager with an impressive collection of libraries and gadgets. Worth having a good tool chain on your system even if you are not allowed to use it for production. You can test against it, for example. – user4581301 May 03 '22 at 19:15
  • @vik by most you must be talking about something other than MS, because they've supported it native since vs2013, nine years ago, and clang and mingw even longer than that. If you're referring to being pinned to EOL toolchains due to some asinine corporate policy, I can absolutely relate, and you have my sympathies. that's always rough. I still remember the glorious day when my work finally agreed to let me move to vs2015u3. I literally cried. – WhozCraig May 03 '22 at 19:39
  • 1
    There is another matter that is *very* important if you're pinned to an ms toolchain. unless you're using strictly winapi artifacts (and I mean *strictly* in the most draconian sense), if you're using the vc++ runtime you should be using `_beginthreadex` for your thread creation, not CreateThread. The latter does not include the per-thread setup and teardown performed by the runtime library hooks. The vernacular is similar (but *not* identical) to CreateThread. – WhozCraig May 03 '22 at 19:44

1 Answers1

2

The thread start routine needs to have the signature:

DWORD __stdcall ThreadFunc(LPVOID lpThreadParameter);

So, you need to cast the void* into the pointer type which you sent into the function:

DWORD WINAPI ThreadFunc(LPVOID lpThreadParameter) {
    std::string& message = *static_cast<std::string*>(lpThreadParameter);
    std::cout<<message;
    return 0;
}

Just note that the string must not be destroyed while the thread is using it.

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • In which case, it is usually customary to allocate the `std::string` dynamically when passing it to the thread, and then have the thread destroy it when done using it. An easier way to handle that is to use `std::thread` instead of `CreateThread()` so the `std::string` can be passed in by value instead of by pointer. – Remy Lebeau May 03 '22 at 21:29
  • @RemyLebeau I agree but OP says that `std::thread` isn't available in the compiler he/she needs to use. – Ted Lyngmo May 03 '22 at 21:32