I have posted about this problem before. SInce then I found a much better article to help with embedding python in a multithreaded application:
http://www.linuxjournal.com/article/3641 I found this article very good and it clarified for me what needs doing. Now I have an example application that almost works, but it is far from reliable. If I run this several times I get crashes telling me that the heap is modified after deallocation. Can anybody else reproduce this? At the bottom of this file I left a debug dump, and a stack dump. Here is my application, compile in windows using a standard windows application project. #include <afxmt.h> #include <afxwin.h> #include <stdio.h> #include <Python.h> #include <Windows.h> #include <process.h> static int threadnum = 0; UINT MyThread(LPVOID lpParam) { ASSERT(Py_IsInitialized()); threadnum++; PyThreadState* mainThreadState = (PyThreadState *)lpParam; // get the global lock PyEval_AcquireLock(); // get a reference to the PyInterpreterState PyInterpreterState * mainInterpreterState = mainThreadState->interp; PyThreadState_Swap(mainThreadState); // create a thread state object for this thread PyThreadState * myThreadState = PyThreadState_New(mainInterpreterState); // free the lock PyEval_ReleaseLock(); // lock - swap in thread state - swap out thread state - unlock PyEval_AcquireLock(); PyThreadState_Swap(myThreadState); int num = 0; int ret = 0; ret = PyRun_SimpleString("x = []"); ret = PyRun_SimpleString("for i in range(10):\n x.append(i)"); char cmd[100]; sprintf(cmd, "f = open('c:/windows/temp/test%d.txt', 'w')", threadnum); ret = PyRun_SimpleString(cmd); ret = PyRun_SimpleString("f.write('%s\\n' % x.__str__())"); sprintf(cmd, "f.write('0x%d\\n')", &myThreadState); ret = PyRun_SimpleString(cmd); ret = PyRun_SimpleString("f.close()"); PyThreadState_Swap(NULL); PyEval_ReleaseLock(); // clean up // grab the lock PyEval_AcquireLock(); // swap my thread state out of the interpreter PyThreadState_Swap(NULL); // clear out any cruft from thread state object PyThreadState_Clear(myThreadState); // delete my thread state object PyThreadState_Delete(myThreadState); // release the lock PyEval_ReleaseLock(); return 0; } class CMyWinApp : public CWinApp { public: CMyWinApp() { } BOOL InitInstance() { Py_Initialize(); PyEval_InitThreads(); // save a pointer to the main PyThreadState object PyThreadState * mainThreadState = PyThreadState_Get(); // release the lock PyEval_ReleaseLock(); const int nhandles = 100; HANDLE hnd[nhandles]; CWinThread* pThread[nhandles]; for (int ih = 0; ih < nhandles; ih++) { pThread[ih] = AfxBeginThread(MyThread, mainThreadState, THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED); pThread[ih]->m_bAutoDelete = false; pThread[ih]->ResumeThread(); hnd[ih] = pThread[ih]->m_hThread; } int nwaits, nfails; do { nwaits = 0; nfails = 0; for (int ih = 0; ih < nhandles; ih++) { DWORD ret = WaitForSingleObject(hnd[ih], INFINITE); switch (ret) { case WAIT_OBJECT_0: printf("WAIT_OBJECT_0\n"); break; case WAIT_TIMEOUT: ++nwaits; printf("WAIT_TIMEOUT\n"); break; case WAIT_FAILED: ++nfails; printf("WAIT_FAILED\n"); break; } } } while (nwaits > 0); ASSERT(nfails == 0); // delete all windows threads for (int ih = 0; ih < nhandles; ++ih) delete pThread[ih]; PyEval_AcquireLock(); PyThreadState_Swap(mainThreadState); Py_Finalize(); return TRUE; }; }; CMyWinApp app; Debug dump: 'pyembed_test.exe': Loaded 'C:\mdunschen\pyembed_test\Debug\pyembed_test.exe', Symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\ntdll.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\mscoree.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\kernel32.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\advapi32.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\rpcrt4.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\user32.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\gdi32.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\comctl32.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\shlwapi.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\msvcrt.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\oleacc.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\msvcp60.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\ole32.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\oleaut32.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\winspool.drv', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\comdlg32.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\shell32.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\python24.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\msvcr71.dll', Symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.2180_x-ww_a84f1ff9\comctl32.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\mscorwks.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\fusion.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\mscorlib.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\assembly\NativeImages1_v1.1.4322\mscorlib\1.0.5000.0__b77a5c561934e089_ca105f6f\mscorlib.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\diasymreader.dll', No symbols loaded. 'DefaultDomain': Loaded 'c:\windows\microsoft.net\framework\v1.1.4322\mscorlib.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\mscorsn.dll', No symbols loaded. 'pyembed_test': Loaded 'c:\mdunschen\pyembed_test\Debug\pyembed_test.exe', Symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\mscorjit.dll', No symbols loaded. 'pyembed_test.exe': Loaded 'C:\WINDOWS\system32\uxtheme.dll', No symbols loaded. The thread '_threadstartex' (0x500) has exited with code 0 (0x0). The thread '_threadstartex' (0xadc) has exited with code 0 (0x0). The thread '<No Name>' (0xadc) has exited with code 0 (0x0). The thread '<No Name>' (0x500) has exited with code 0 (0x0). The thread '_threadstartex' (0x928) has exited with code 0 (0x0). The thread '<No Name>' (0x928) has exited with code 0 (0x0). The thread '_threadstartex' (0xe48) has exited with code 0 (0x0). The thread '<No Name>' (0xe48) has exited with code 0 (0x0). The thread '_threadstartex' (0x984) has exited with code 0 (0x0). The thread '<No Name>' (0x984) has exited with code 0 (0x0). The thread '_threadstartex' (0x108) has exited with code 0 (0x0). HEAP[pyembed_test.exe]: HEAP: Free Heap block eb5bd8 modified at eb5c24 after it was freed Unhandled exception at 0x7c901230 in pyembed_test.exe: User breakpoint. Stack dump: > pyembed_test.exe!_heap_alloc_dbg(unsigned int nSize=15400960, int > nBlockUse=1073741920, const char * szFileName=0x00000064, int nLine=1242368) > Line 359 + 0x1e C pyembed_test.exe!_heap_alloc_base(unsigned int size=100) Line 212 C pyembed_test.exe!_heap_alloc_dbg(unsigned int nSize=64, int nBlockUse=12582916, const char * szFileName=0x004c4dd4, int nLine=311) Line 397 + 0x9 C pyembed_test.exe!_nh_malloc_dbg(unsigned int nSize=64, int nhFlag=0, int nBlockUse=12582916, const char * szFileName=0x004c4dd4, int nLine=311) Line 260 + 0x15 C pyembed_test.exe!_malloc_dbg(unsigned int nSize=64, int nBlockUse=12582916, const char * szFileName=0x004c4dd4, int nLine=311) Line 176 + 0x1b C pyembed_test.exe!operator new(unsigned int nSize=64, int nType=12582916, const char * lpszFileName=0x004c4dd4, int nLine=311) Line 403 + 0x15 C++ pyembed_test.exe!CObject::operator new(unsigned int nSize=64, const char * lpszFileName=0x004c4dd4, int nLine=311) Line 93 + 0x16 C++ pyembed_test.exe!AfxBeginThread(unsigned int (void *)* pfnThreadProc=0x00401b80, void * pParam=0x00df7b10, int nPriority=0, unsigned int nStackSize=4, unsigned long dwCreateFlags=0, _SECURITY_ATTRIBUTES * lpSecurityAttrs=0x00000000) Line 311 + 0x11 C++ 00aaa43d() pyembed_test.exe!CMyWinApp::InitInstance() Line 87 + 0x26 bytes C++ pyembed_test.exe!AfxWinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ * hPrevInstance=0x00000000, char * lpCmdLine=0x00141f12, int nCmdShow=5) Line 39 + 0xb C++ pyembed_test.exe!WinMain(HINSTANCE__ * hInstance=0x00400000, HINSTANCE__ * hPrevInstance=0x00000000, char * lpCmdLine=0x00141f12, int nCmdShow=5) Line 25 C++ pyembed_test.exe!WinMainCRTStartup() Line 251 + 0x30 C -- http://mail.python.org/mailman/listinfo/python-list