Вызов _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 в таких случаях, и если да, то как? Любые мысли будут оценены.
2 ответа
Нашел ответ, который я искал - это выполнимо и его конверсия имеет значение, как сказала Лоис. Следующий код делает это возможным, компилирует и распространяет поток;-)
return (HANDLE) _beginthreadex(NULL, NULL,(unsigned (__stdcall*)(void*)) pFunction, pvFuncArgs, NULL, NULL);
Спасибо всем.
Что вы подразумеваете под "неизвестно и НЕ основано на дизайне класса"? Для одного, _beginthreadex()
не является объектно-ориентированным API.
Что касается известной части, хорошо: при использовании указателя на функцию компилятору по крайней мере необходимо знать, где указанная функция (ее адрес) и как ее вызывать (какие параметры она ожидает и какие значения она возвращает). Если вы отклоняетесь от этого контракта, ничто не гарантируется: вызов может закончиться надежной работой или нет в зависимости от сгенерированного кода.
В вашем примере _beginthreadex()
говорит вам, что ожидает функцию, которая использует __stdcall
соглашение, принимает адрес в качестве параметра и не возвращает результатов. Вы даете ему функцию, которая возвращает int
и принимает параметр адреса, но (при условии, что настройки компилятора по умолчанию) использует обычное соглашение о вызовах C вместо __stdcall
: поэтому возможно некоторое повреждение стека. Используя приведение, вы просто указываете компилятору прекратить жаловаться и генерировать вызов (какими бы ни были последствия).
Если вы хотите сделать что-то, как в вашем примере, безопаснее дать _beginthreadex()
__stdcall
функция, которая вызывает любую функцию, которую вы действительно хотите использовать.