Вызов _beginthreadx с указателями на функцию Passing

Мне интересно знать, возможно ли вызвать _beginthreadex с указателем на функцию, которая неизвестна и НЕ основана на дизайне класса.
Например:

#include <stdio.h>
#include <process.h>
#include <windows.h>

int myThread(void* data)
{
printf("ThreadID: %d \n", GetCurrentThreadId());
return 1;
}

HANDLE callIntThreadFunc(void (*pFunction)(LPVOID), LPVOID pvFuncArgs)
{
//Expected to fail compilation due to __stcall
return (HANDLE) _beginthreadex(NULL, NULL, pFunction, (LPVOID) pvFuncArgs, NULL, NULL);
}

int main(int argc, char *argv[])
{
HANDLE hThread = callIntThreadFunc(myThread, NULL);
WaitForSingleObject(hThread , INFINITE);

return 0;
}

Я знаю, что _beginthread может работать при преобразовании функции (с помощью следующего кода):

return (HANDLE) _beginthread((void (*)(void*)) pFunction, 0, (LPVOID) pvFuncArgs);

Поэтому мой вопрос: возможно ли использовать _beginthreadex в таких случаях, и если да, то как?
Любые мысли будут оценены.

1

Решение

Что вы подразумеваете под «не известен и НЕ основан на дизайне класса«? Для одного, _beginthreadex() не является объектно-ориентированным API.

Что касается известен отчасти, хорошо: при использовании указателя на функцию компилятору, по крайней мере, нужно будет знать, где указанная функция (ее адрес) и как ее вызывать (какие параметры она ожидает и какие значения она возвращает). Если вы отклоняетесь от этого контракта, ничего не гарантировано: вызов может закончиться надежной работой или нет в зависимости от сгенерированного кода.

В вашем примере _beginthreadex() говорит вам, что ожидает функцию, которая использует __stdcall соглашение, принимает адрес в качестве параметра и не возвращает результатов. Вы даете ему функцию, которая возвращает int и принимает параметр адреса, но (при условии, что настройки компилятора по умолчанию) использует обычное соглашение о вызовах C вместо __stdcall: поэтому возможно некоторое повреждение стека. Используя приведение, вы просто указываете компилятору прекратить жаловаться и генерировать вызов (какими бы ни были последствия).

Если вы хотите сделать что-то, как в вашем примере, безопаснее дать _beginthreadex() __stdcall функция, которая вызывает любую функцию, которую вы действительно хотите использовать.

1

Другие решения

Нашел ответ, который я искал — это выполнимо и его конверсия имеет значение, как сказала Лоис.
Следующий код делает это возможным, компилирует и распространяет поток 😉

return (HANDLE) _beginthreadex(NULL, NULL,(unsigned (__stdcall*)(void*)) pFunction, pvFuncArgs, NULL, NULL);

Спасибо всем.

0