C ++에서 기능 포인터를 전달합니다
-
03-07-2019 - |
문제
이 간단한 코드 작업을하고 싶습니다.
#include <iostream>
#include <windows.h>
void printSome (int i)
{
std::cout << i << std::endl;
}
void spawnThread (void (*threadName)(int i))
{
CreateThread
(
0, // default security attributes
0, // use default stack size
(LPTHREAD_START_ROUTINE)threadName, // thread function name
(LPVOID)i, // argument to thread function
0, // use default creation flags
0 // returns the thread identifier
);
}
int main ()
{
spawnThread(printSome(155));
}
나는 Windows에 있으며, 모든 도움을 사용하는 것은 크게 걱정할 것입니다.
해결책
개인적으로, 나는 당신이 매우 c ++처럼하려고하는 것처럼 함수 포인터를 통과하는 것을 고려하지 않을 것입니다. C ++에서 C를 코딩하고 있습니다
대신, 나는 그 일을 수업에서 감싸고 있습니다. 큰 장점은 매번 매개 변수를 얻기 위해 Greazy 캐스팅 트릭을 수행하지 않고 원하는 많은 회원을 갖도록 수업을 무시할 수 있습니다.
코드는 조금 길고 끝까지 밀어 넣었습니다. 그러나 그것이 당신이 할 수있는 것은 다음과 같습니다.
class print_some : public basic_thread {
private:
int i;
public:
print_some (int i) : i(i) {};
action_callback () {
std::cout << i << std::endl;
}
}
int main () {
print_some printer (155);
}
다음은 수업 중 하나의 수용된 예제 코드입니다.
class basic_thread :
{
public:
basic_thread();
protected:
unsigned long m_ThreadId;
virtual void action_callback () {};
// Internal routine used to bridge between OS callback format and
// action_callback. *Must* be static for the OS.
static unsigned long __stdcall self_calling_callback (void *parameter);
}
... 그리고 .cpp에서 :
unsigned long __stdcall basic_thread::self_calling_callback (void *parameter) {
if (parameter) {
basic_thread * thread = reinterpret_cast<basic_thread *>(parameter);
thread->action_callback();
}
return 0; // The value returned only matters if someone starts calling GetExitCodeThread
// to retrieve it.
}
basic_thread::basic_thread () {
// Start thread.
m_Handle = CreateThread(NULL,
0,
self_calling_callback,
(PVOID)this,
0,
&m_ThreadId );
if( !IsHandleValid() )
throw StartException("CreateThread() failed", GetLastError());
}
다른 팁
CreateThread는 2 인수를 원합니다 : 스레드로 실행하는 기능에 대한 포인터, 그리고 스레드에 주어진 dword 인수. spawnthread () 함수는 1 인수 (threadName) 만 있습니다. 너 생각한다 "I"때문에 2 개의 Args가 있지만 실제로 "ThreadName"유형의 정의의 일부입니다. (당신은 "I"를 제외 할 수 있습니다. 즉, "ThreadName"에 대한 인수를 지명 할 필요는 없습니다.)
어쨌든, 당신이 2 개의 인수가 필요하다는 것을 감안할 때, spawnthread를 재정의합니다.
void spawnThread(void (*threadEntryPoint)(int), int argument)
{
CreateThread(0,0,
(LPTHREAD_START_ROUTINE)threadEntryPoint,
(LPVOID)argument,
0,0);
}
내가하지 않았다는 것을 주목하십시오 이름 ThreadentRyPoint에 대한 인수; 컴파일러에 함수에 단일 INT 인수가 있어야한다고 말하는 것이 충분합니다.
그리고 그것을 호출하십시오 :
spawnThread(printSome, 155);
어쨌든, 빠르고 더럽 으면, 이것은 당신이 원하는 것을 할 것입니다.
HTH.
레일리.
함수 포인터에서 매개 변수 정보를 전달할 수 없습니다. 별도로 통과해야합니다. 이것이 바로 CreateTheRad 기능이 원하는 것을 가리킬 수있는 무효* 매개 변수를 제공하는 이유입니다.
또한, 당신은해야합니다 CreateThread 대신 _beginthread를 사용하십시오 C ++ 응용 프로그램의 경우.
마지막으로, 스레드가 실행되기 전에 프로그램이 종료 될 가능성이 높습니다. 따라서 무기한 루프를 입력하거나 API 호출을 사용하여 스레드가 완료 될 때까지 기다려야합니다.
다음은 사용하는 작업 버전입니다 WaitforsingleObject 스레드가 완료 될 때까지 차단합니다.
#include <iostream>
#include <process.h>
#include <windows.h>
void
printSome(int i)
{
std::cout << i << std::endl;
}
HANDLE
spawnThread(void (*threadName)(int), int i)
{
return (HANDLE) _beginthread((void (*)(void*)) threadName, 0, (LPVOID) i);
}
int
main(int argc, char *argv[])
{
HANDLE threadHandle;
threadHandle = spawnThread(printSome, 155);
WaitForSingleObject(threadHandle, INFINITE);
return 0;
}
다음은 동일한 상황을 처리하는 훨씬 더 C ++/객체 지향 방법입니다.
#include <iostream>
#include <process.h>
#include <windows.h>
class Thread {
static void proxy(void *arg) { (*(reinterpret_cast<Thread *> (arg)))(); }
HANDLE thread_;
public:
virtual ~Thread() {}
virtual void operator()() = 0;
void start() { thread_ = (HANDLE) _beginthread(Thread::proxy, 0, this);}
void waitForExit() { WaitForSingleObject(thread_, INFINITE); }
};
class Printer : public Thread {
int i_;
public:
Printer(int i) : i_(i) {}
void operator()() { std::cout << i_ << std::endl; }
};
int
main(int argc, char *argv[])
{
Printer p(155);
p.start();
p.waitForExit();
return 0;
}
많은 사람들이 이미 여기에 언급했듯이 함수 포인터와 그 인수는 하나의 매개 변수로 호출되어야합니다.
당신의 라인
spawnThread(printSome(155));
"DWIM 세계에서)는"인수가있는 별도의 스레드에서 printsome을 호출한다 "를 의미합니다. 그러나 C ++가 그것을 이해하는 방법은 아닙니다. C ++는 "Spawnthread의 매개 변수로 155에서 호출 된 Printsome의 결과를 통과합니다." 다시 말해, 일련의 단계는 다음과 같습니다.
- 논쟁으로 155로 prinotsome을 호출하십시오. 임시 메모리에 저장하십시오.
- 임시 메모리의 내용을 인수로 SpawnThread를 호출하십시오.
당신이 실제로 의미하는 바를 수행하려면 C ++를 유머하고 기능과 분리해야합니다. 그것을하는 방법은 이미 다른 답변으로 설명되어 있습니다. 그것의 부족은 다음과 같습니다.
callonotherthreadwithargument (함수, 정수);
여기서 어떻게하는지 읽을 수 있습니다. http://www.newty.de/fpt/fpt.html
2.6 인수로 함수 포인터를 전달하는 방법은 무엇입니까?
함수의 호출 인수로 함수 포인터를 전달할 수 있습니다. 예를 들어 포인터를 콜백 함수로 전달하려는 경우이 작업이 필요합니다. 다음 코드는 int를 반환하고 플로트와 두 숯을 가져 오는 함수로 포인터를 전달하는 방법을 보여줍니다.
//------------------------------------------------------------------------------------
// 2.6 How to Pass a Function Pointer
// <pt2Func> is a pointer to a function which returns an int and takes a float and two char
void PassPtr(int (*pt2Func)(float, char, char))
{
int result = (*pt2Func)(12, 'a', 'b'); // call using function pointer
cout << result << endl;
}
// execute example code - 'DoIt' is a suitable function like defined above in 2.1-4
void Pass_A_Function_Pointer()
{
cout << endl << "Executing 'Pass_A_Function_Pointer'" << endl;
PassPtr(&DoIt);
}