I'm using threads in Windows to connect a plug-in made in c++ to a python script. The thread is to be called many times in the duration of the session
Question:
If I pass the ArgList
in the _beginthread
the error "Unhandled exception at 0x1E114A68 (python27.dll) in xxx.exe: 0xC0000005: Access violation reading location 0xFFFFFFFE." is raised and I think it's because of this i read in CreatingThreads of Windows Dev Center:
" Note that if you were to close the handle to a worker thread before it terminated, this does not terminate the worker thread. However, the handle will be unavailable for use in subsequent function calls."
Am I right about the origin of this error? How do I work past this?
Code:
I called _beginthread
with NULL
as the ArgList
and defined the ArgList
inside the worker thread just for getting the thread to work. Here's the code for the worker thread:
Note: I noticed while debugging that _endthread()
is not reached. Is that normal?
void py_embed (void*data){
char *argv[4]={"PythonPlugIn2","bridge","test_callsign","MAH543"};
int argc=4;
ofstream textfile3;
textfile3.open("FP_python_embed.txt");
PyObject *pName, *pModule, *pDict, *pFunc, *pArgs, *pValue;
PyThreadState *mainThreadState,*myThreadState,*tempState;
PyInterpreterState *mainInterpreterState;
//To inform the interpreter about paths to Python run-time libraries
Py_SetProgramName(argv[0]);
// Initialize the Python Interpreter
Py_Initialize();
// Initialize thread support
PyEval_InitThreads();
// Save a pointer to the main PyThreadState object
mainThreadState = PyThreadState_Get();
// Get a reference to the PyInterpreterState
mainInterpreterState = mainThreadState->interp;
// Create a thread state object for this thread
myThreadState = PyThreadState_New(mainInterpreterState);
// Release global lock
PyEval_ReleaseLock();
// Acquire global lock
PyEval_AcquireLock();
// Swap in my thread state
tempState = PyThreadState_Swap(myThreadState);
// Build the name object
pName = PyString_FromString(argv[1]);
// Load the module object
pModule = PyImport_Import(pName);
// pDict is a borrowed reference
pDict = PyModule_GetDict(pModule);
// pFunc is also a borrowed reference
pFunc = PyDict_GetItemString(pDict, argv[2]);
//Do the Python things
PyObject *pArgs2, *pValue2;
pArgs2=Py_BuildValue("(s)",argv[3]);
pValue2 = PyObject_CallObject(pFunc, pArgs2);
textfile3<<PyInt_AsLong(pValue2)<<endl<<" worked1";
textfile3.close();
// Clean up
Py_DECREF(pModule);
Py_DECREF(pName);
// Swap out the current thread
PyThreadState_Swap(tempState);
// Release global lock
PyEval_ReleaseLock();
// Clean up thread state
PyThreadState_Clear(myThreadState);
PyThreadState_Delete(myThreadState);
// Finish the Python Interpreter
Py_Finalize();
_endthread();
};
And what I do to call it from the main thread(that closes before the worker thread is finished):
handle=(HANDLE) _beginthread(py_embed,0,NULL);
NOTE:Question 1 related to this is here
So, i finally found the problem. Hope this helps anyone who has the same problem i did
I still don't fully understand how this works but i basically need to dynamically allocate memory on the heap using new
in c++ (and malloc
in c). More information about this here
In my case I will need to do something like this:
#define NUM_ARGUMENTS 4
typedef struct{
int argc;
char *argv[NUM_ARGUMENTS];
}SENDTOPY;
And then on the main thread:
SENDTOPY *cmd;
char *argv[4]={"PythonPlugIn2","bridge","test_callsign","MAH543"};
int i;
cmd= new SENDTOPY();
cmd->argc=4;
for( i = 0; i < NUM_ARGUMENTS; i++ )
{cmd->argv[i] = argv[i];}
handle=(HANDLE) _beginthread(py_embed,0,(void*)cmd);
I still need to understand this better, and also learn how to deallocate at the end with delete
but I'm in the right way.
Note: I still need help on the Question1 related to this, so please have a look at it.
User contributions licensed under CC BY-SA 3.0