我有a解決方案適用於此,但如果我可以用Python而不是C++捕獲信號,它會更乾淨。
一件事之前我沒有提到的是,myObject的是一個單身,所以我用MyObject.getObject()
在Python得到它,我已經有了:
def signalHandler(signum) :
if signum == signal.SIGINT :
MyObject.getObject().stop()
def main() :
signal.signal(signal.SIGINT, handle_interrupt)
myObject = MyObject.getObject()
myObject.addSignalHandler(signal.SIGINT, signalHandler)
myObject.start()
在我的C++代碼在一個地區,不應該知道的Python什麼,我有:
class MyObject
{
public :
void addSignalHandler(int signum, void (*handler)(int, void*), void *data = nullptr);
void callSignalHandler(int signum);
private :
std::map<int, std::pair<void (*)(int, void*), void*> > m_signalHandlers;
}
void signalCallbackHandler(int signum)
{
MyObject::getObject()->callSignalHandler(signum);
}
void MyObject::addSignalHandler(int signum, void (*handler)(int, void*), void *data)
{
m_signalHandlers.insert(std::pair<int, std::pair<void (*)(int, void*), void *> >(signum, std::make_pair(handler, data)));
signal(signum, signalCallbackHandler);
}
void MyObject::callSignalHandler(int signum)
{
std::map<int, std::pair<void (*)(int, void*), void*> >::iterator handler = m_signalHandlers.find(signum);
if(handler != m_signalHandlers.end())
{
handler->second.first(signum, handler->second.second);
}
}
然後在我的Python綁定:
void signalHandlerWrapper(int signum, void *data)
{
if(nullptr == data)
{
return;
}
PyObject *func = (PyObject*)(data);
if(PyFunction_Check(func))
{
PyObject_CallFunction(func, "i", signum);
}
}
void addSignalHandlerWrapper(MyObject *o, int signum, PyObject *func)
{
Py_INCREF(func);
if(PyFunction_Check(func))
{
o->addSignalHandler(signum, &signalHandlerWrapper, func);
}
}
我沒有,我應該補充說,是addSignalHandlerWrapper()中的一些東西,它將檢查是否已經存在某個信號編號,如果是,則在添加新的函數之前獲取它並減少引用一。我還沒有這樣做,因爲這個功能只用於結束程序,但爲了完整性,它應該放在適當的位置。
無論如何,正如我在開始時所說的那樣,這比參與其中的可能性更大。它也只適用於我有一個可以跟蹤函數指針的單例。
如果您的擴展程序代碼在後臺線程中運行,請確保釋放GIL。在主線程中,不要忘記在C代碼中的信號中斷阻塞系統調用之後,定期或在「errno == EINTR」上調用'PyErr_CheckSignals()'(同時保持GIL)。相關:[Cython,Python和KeyboardInterrupt被忽略](http://stackoverflow.com/q/16769870/4279)。這裏是[更多細節(用俄語) - 查看代碼示例](http://ru.stackoverflow.com/a/573288/23044) – jfs