怎么让linux上qt也能执行,如何使用Qt在Windows和Linux上执行Ctrl + C

这篇博客介绍了一个类,用于在C++控制台应用程序中捕获信号,使得Qt应用在Windows和Linux上都能响应Ctrl+C。通过SetConsoleCtrlHandler()函数在Windows上和特定的POSIX函数在其他平台处理信号,实现不同平台的兼容。该类还提供了一种方式来处理不同的信号,如SIG_INT、SIG_TERM等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我使用这个类来捕获C++控制台应用程序中的信号。但是,这并不是Qt特有的。它在Windows平台上使用SetConsoleCtrlHandler(),并在其他平台上使用提供的函数。棘手的一点是“信号”不是一个跨平台术语 - Windows和POSIX对它们有不同的定义。无论如何,这个班级试图将他们映射到一个共同的词汇。 Ctrl^C是在两个平台上很好的映射。

我希望这可以适应您的具体情况。请注意,错误检查很少,应该可以改进。

用法(main.cpp中)

#include "SignalHandler.h"

class Application : public SignalHandler

{

public:

Application() : SignalHandler(SignalHandler::SIG_INT), myThread(NULL) {}

int Application::main(int argc, char *argv[])

{

// Main program instructions here (e.g. start a thread)

myThread = new Thread(...);

myThread->start();

myThread->join();

delete myThread;

return 0;

}

bool handleSignal(int signal)

{

std::cout << "Handling signal " << signal << std::endl;

if (_myThread && _myThread->isRunning())

{

_myThread->stop();

// The thread is going to stop soon, so don't propagate this signal further

return true;

}

// Let the signal propagate as though we had not been there

return false;

}

private:

Thread* myThread;

};

int main(int argc, char* argv[])

{

Application app;

return app.main(argc, argv);

}

SignalHandler.h

class SignalHandler

{

public:

SignalHandler(int mask = DEFAULT_SIGNALS);

virtual ~SignalHandler();

enum SIGNALS

{

SIG_UNHANDLED = 0, // Physical signal not supported by this class

SIG_NOOP = 1, // The application is requested to do a no-op (only a target that platform-specific signals map to when they can't be raised anyway)

SIG_INT = 2, // Control+C (should terminate but consider that it's a normal way to do so; can delay a bit)

SIG_TERM = 4, // Control+Break (should terminate now without regarding the consquences)

SIG_CLOSE = 8, // Container window closed (should perform normal termination, like Ctrl^C) [Windows only; on Linux it maps to SIG_TERM]

SIG_RELOAD = 16, // Reload the configuration [Linux only, physical signal is SIGHUP; on Windows it maps to SIG_NOOP]

DEFAULT_SIGNALS = SIG_INT | SIG_TERM | SIG_CLOSE,

};

static const int numSignals = 6;

virtual bool handleSignal(int signal) = 0;

private:

int _mask;

};

SignalHandler.cpp

#include "SignalHandler.h"

#include

#ifndef _WIN32

#include

#else

#include

#endif //!_WIN32

// There can be only ONE SignalHandler per process

SignalHandler* g_handler(NULL);

#ifdef _WIN32

BOOL WINAPI WIN32_handleFunc(DWORD);

int WIN32_physicalToLogical(DWORD);

DWORD WIN32_logicalToPhysical(int);

std::set g_registry;

#else //_WIN32

void POSIX_handleFunc(int);

int POSIX_physicalToLogical(int);

int POSIX_logicalToPhysical(int);

#endif //_WIN32

SignalHandler::SignalHandler(int mask) : _mask(mask)

{

assert(g_handler == NULL);

g_handler = this;

#ifdef _WIN32

SetConsoleCtrlHandler(WIN32_handleFunc, TRUE);

#endif //_WIN32

for (int i=0;i

{

int logical = 0x1 << i;

if (_mask & logical)

{

#ifdef _WIN32

g_registry.insert(logical);

#else

int sig = POSIX_logicalToPhysical(logical);

bool failed = signal(sig, POSIX_handleFunc) == SIG_ERR;

assert(!failed);

(void)failed; // Silence the warning in non _DEBUG; TODO: something better

#endif //_WIN32

}

}

}

SignalHandler::~SignalHandler()

{

#ifdef _WIN32

SetConsoleCtrlHandler(WIN32_handleFunc, FALSE);

#else

for (int i=0;i

{

int logical = 0x1 << i;

if (_mask & logical)

{

signal(POSIX_logicalToPhysical(logical), SIG_DFL);

}

}

#endif //_WIN32

}

#ifdef _WIN32

DWORD WIN32_logicalToPhysical(int signal)

{

switch (signal)

{

case SignalHandler::SIG_INT: return CTRL_C_EVENT;

case SignalHandler::SIG_TERM: return CTRL_BREAK_EVENT;

case SignalHandler::SIG_CLOSE: return CTRL_CLOSE_EVENT;

default:

return ~(unsigned int)0; // SIG_ERR = -1

}

}

#else

int POSIX_logicalToPhysical(int signal)

{

switch (signal)

{

case SignalHandler::SIG_INT: return SIGINT;

case SignalHandler::SIG_TERM: return SIGTERM;

// In case the client asks for a SIG_CLOSE handler, accept and

// bind it to a SIGTERM. Anyway the signal will never be raised

case SignalHandler::SIG_CLOSE: return SIGTERM;

case SignalHandler::SIG_RELOAD: return SIGHUP;

default:

return -1; // SIG_ERR = -1

}

}

#endif //_WIN32

#ifdef _WIN32

int WIN32_physicalToLogical(DWORD signal)

{

switch (signal)

{

case CTRL_C_EVENT: return SignalHandler::SIG_INT;

case CTRL_BREAK_EVENT: return SignalHandler::SIG_TERM;

case CTRL_CLOSE_EVENT: return SignalHandler::SIG_CLOSE;

default:

return SignalHandler::SIG_UNHANDLED;

}

}

#else

int POSIX_physicalToLogical(int signal)

{

switch (signal)

{

case SIGINT: return SignalHandler::SIG_INT;

case SIGTERM: return SignalHandler::SIG_TERM;

case SIGHUP: return SignalHandler::SIG_RELOAD;

default:

return SignalHandler::SIG_UNHANDLED;

}

}

#endif //_WIN32

#ifdef _WIN32

BOOL WINAPI WIN32_handleFunc(DWORD signal)

{

if (g_handler)

{

int signo = WIN32_physicalToLogical(signal);

// The std::set is thread-safe in const reading access and we never

// write to it after the program has started so we don't need to

// protect this search by a mutex

std::set::const_iterator found = g_registry.find(signo);

if (signo != -1 && found != g_registry.end())

{

return g_handler->handleSignal(signo) ? TRUE : FALSE;

}

else

{

return FALSE;

}

}

else

{

return FALSE;

}

}

#else

void POSIX_handleFunc(int signal)

{

if (g_handler)

{

int signo = POSIX_physicalToLogical(signal);

g_handler->handleSignal(signo);

}

}

#endif //_WIN32

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值