try { do some python script... } catch(boost::python::error_already_set) { PyErr_Print(); PyRun_SimpleString("sys.stderr.showmsg()"); } 来执行一下showmsg。 关于python似乎比较郁闷的问题就这些了。
3.多线程
我发现第一次写多线程程序的时候可能都会这样。。。完全意识不到在使用别人的库的时候一定要去关心一下多线程。比如: 3.1在子线程中使用wxURL,wxFTP之类的从wxSocketBase继承的类,一定要记得在最开始的时候手动调用一个wxSocketBase::Initialize(); 3.2在子线程中使用mysql记得mysql_thread_init();和mysql_thread_end(); 3.3在子线程中使用CrashRpt记得crInstallToCurrentThread()和crUninstallFromCurrentThread() 3.4 上面就是3.1比较隐含一点,因为它表现出来的是有的时候用GetInputStream的时候会得到NULL你还以为是网络卡没打开。而wxSocketBase::Initialize();的要求写在一个小小的角落里很容易被人忽视。 更加隐含的一个错误就是在子线程中调用python脚本。这个太痛苦了。因为几乎它从来都不出错,几乎从来都没问题,但是偶尔就会出一些非常奇怪的问题,不,不会挂掉,只会是结果与你想象的不符合。 在子线程中使用python的办法是这样的:首先你需要PyEval_InitThreads(); 因为我的python脚本本质上同时只运行一个,所以我这里实际是“单线程”,更复杂的情况就不知道了。 我顺手就PyEval_ReleaseLock();以后谁要执行脚本谁来PyEval_AcquireLock(); 主线程中执行,就在执行前PyEval_AcquireLock();执行后PyEval_ReleaseLock(); 子线程中就这样,执行前: // get the global lock PyEval_AcquireLock();
PyThreadState * mainThreadState = NULL; // save a pointer to the main PyThreadState object mainThreadState = PyThreadState_Get();
// get a reference to the PyInterpreterState PyInterpreterState * mainInterpreterState = mainThreadState->interp; // create a thread state object for this thread m_pMyState = PyThreadState_New(mainInterpreterState); m_pSavedState = PyThreadState_Swap(m_pMyState);
执行后: PyThreadState_Swap(m_pSavedState); PyThreadState_Clear(m_pMyState); // delete my thread state object PyThreadState_Delete(m_pMyState);
// release our hold on the global interpreter PyEval_ReleaseLock(); 还有很多更好的做法,你可以去网上查查看。