F
freesteel
I am trying to run a python programme embedded from C++. I want to run
the same python code concurrently in several threads. I read the manual
on embedding, especially chapter 8, and searched for relevant info on
google all afternoon, but I can't get this to work. What am I doing
wrong? I use python2.4 and vc++7 (.net). The first thread seems to work
okay, the 2nd thread crashes, but the exception information is not very
useful:
(An unhandled exception of type 'System.NullReferenceException'
occurred in pyembed_test.exe
Additional information: Object reference not set to an instance of an
object.)
Here is a simplified example, it is heavily based on this article:
http://www.codeproject.com/cpp/embedpython_1.asp
#include <afxwin.h>
#include <Python.h>
#include <Windows.h>
#include <process.h>
#define USE_AFX 0
#if USE_AFX
UINT MyThread(LPVOID lpParam)
#else
void MyThread(void* lpParam)
#endif
{
Py_Initialize();
//#if 0
// PyEval_InitThreads();
PyThreadState *mainthreadstate = PyThreadState_Get();
PyInterpreterState *maininterpreterstate = mainthreadstate->interp;
PyThreadState *mythreadstate =
PyThreadState_New(maininterpreterstate);
PyEval_ReleaseLock();
PyEval_AcquireLock();
PyThreadState *tmpstate = PyThreadState_Swap(mythreadstate);
//#endif
int* num = (int *)lpParam;
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('test%d.txt', 'w')", *num);
ret = PyRun_SimpleString(cmd);
ret = PyRun_SimpleString("f.write('%s' % x.__str__())");
ret = PyRun_SimpleString("f.close()");
//#if 0
PyThreadState_Swap(tmpstate);
PyEval_ReleaseLock();
PyThreadState_Clear(mythreadstate);
PyThreadState_Delete(mythreadstate);
//#endif
Py_Finalize();
#if USE_AFX
return 0;
#else
_endthread();
#endif
}
class CMyWinApp : public CWinApp
{
public:
CMyWinApp() { }
BOOL InitInstance()
{
int num0 = 0, num1 = 1;
HANDLE hnd0, hnd1;
#if USE_AFX
CWinThread* pThread0 = AfxBeginThread(MyThread, &num0);
hnd0 = pThread0->m_hThread;
CWinThread* pThread1 = AfxBeginThread(MyThread, &num1);
hnd1 = pThread1->m_hThread;
#else
hnd0 = (HANDLE) _beginthread(MyThread, 0, &num0);
hnd1 = (HANDLE) _beginthread(MyThread, 0, &num1);
#endif
// wait for the worker thread to terminate.
WaitForSingleObject(hnd0, INFINITE);
WaitForSingleObject(hnd1, INFINITE);
return TRUE;
};
};
CMyWinApp app;
the same python code concurrently in several threads. I read the manual
on embedding, especially chapter 8, and searched for relevant info on
google all afternoon, but I can't get this to work. What am I doing
wrong? I use python2.4 and vc++7 (.net). The first thread seems to work
okay, the 2nd thread crashes, but the exception information is not very
useful:
(An unhandled exception of type 'System.NullReferenceException'
occurred in pyembed_test.exe
Additional information: Object reference not set to an instance of an
object.)
Here is a simplified example, it is heavily based on this article:
http://www.codeproject.com/cpp/embedpython_1.asp
#include <afxwin.h>
#include <Python.h>
#include <Windows.h>
#include <process.h>
#define USE_AFX 0
#if USE_AFX
UINT MyThread(LPVOID lpParam)
#else
void MyThread(void* lpParam)
#endif
{
Py_Initialize();
//#if 0
// PyEval_InitThreads();
PyThreadState *mainthreadstate = PyThreadState_Get();
PyInterpreterState *maininterpreterstate = mainthreadstate->interp;
PyThreadState *mythreadstate =
PyThreadState_New(maininterpreterstate);
PyEval_ReleaseLock();
PyEval_AcquireLock();
PyThreadState *tmpstate = PyThreadState_Swap(mythreadstate);
//#endif
int* num = (int *)lpParam;
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('test%d.txt', 'w')", *num);
ret = PyRun_SimpleString(cmd);
ret = PyRun_SimpleString("f.write('%s' % x.__str__())");
ret = PyRun_SimpleString("f.close()");
//#if 0
PyThreadState_Swap(tmpstate);
PyEval_ReleaseLock();
PyThreadState_Clear(mythreadstate);
PyThreadState_Delete(mythreadstate);
//#endif
Py_Finalize();
#if USE_AFX
return 0;
#else
_endthread();
#endif
}
class CMyWinApp : public CWinApp
{
public:
CMyWinApp() { }
BOOL InitInstance()
{
int num0 = 0, num1 = 1;
HANDLE hnd0, hnd1;
#if USE_AFX
CWinThread* pThread0 = AfxBeginThread(MyThread, &num0);
hnd0 = pThread0->m_hThread;
CWinThread* pThread1 = AfxBeginThread(MyThread, &num1);
hnd1 = pThread1->m_hThread;
#else
hnd0 = (HANDLE) _beginthread(MyThread, 0, &num0);
hnd1 = (HANDLE) _beginthread(MyThread, 0, &num1);
#endif
// wait for the worker thread to terminate.
WaitForSingleObject(hnd0, INFINITE);
WaitForSingleObject(hnd1, INFINITE);
return TRUE;
};
};
CMyWinApp app;