Edit done: I am wrapping a custom python dll with the purpose of removing the custom code eventually and using a recent python instead of the ancient version that is being used now. One of the functions initializes a python extension, and calls
PyObject* _PyObject_New(PyTypeObject *type)
In my wrapper the (c) object produced by this call is crashing on PyErr_Print()
(yes i've wrapped it too).
I'd like to experiment with replacing the Repr or Str calls to something of my choosing to see if those are guilty. Also, i can't use capsules because the objects are supposed to be available even on python code.
By request: the real problem is happening wherever one of two c native pointers gets called. I took python 2.7.1 source, opened in on VS 2003 (project is on PC/VS7.1), opened pythonrun.c
there and added stubs of the troika functions at the end:
static CHAR gameHome[MAX_PATH + 1] = { 0 };
__declspec (dllexport) void Py_SetGameInterface(){
//Set the path here
unsigned long nChars;
nChars = GetModuleFileName(NULL, gameHome, MAX_PATH);
if(nChars <= 0){
printf("Failed getting the exe path\n");
return;
}
for( ; nChars > 0; nChars--){
//think windows accepts both
if(gameHome[nChars]=='\\' || gameHome[nChars]=='/'){
break;
}
}
if(nChars == 0){
printf("Failed getting the python path\n");
return;
}
strcpy(&gameHome[nChars+1],"Bin\\python\0");
Py_SetPythonHome(gameHome);
}
/* this was deprecated in python 2.3 but vampire needs it */
#undef _PyObject_Del
__declspec (dllexport) void _PyObject_Del(PyObject *op)
{
PyObject_FREE(op);
}
//original returns the number of chars output
//if you give it a char* youll receive what was written but that
//looks like a accident of the stack
__declspec (dllexport) int Py_FlushConsoleOutput(){
return 0;
}
__declspec (dllexport) int PyRun_ConsoleString(char * str, int typeOfExpression, PyObject * globals, PyObject * locals){
PyObject* ret = NULL;
printf("Console String: %s, size %d\n", str, strlen(str));
if(PyErr_Occurred() != NULL){
printf("WTF ERROR\n%s", PyString_AsString(PyObject_Str(PyErr_Occurred())));
PyErr_Clear();
}
//trying to run dir(cvar) crashes here
ret = PyRun_String(str, typeOfExpression, globals, locals);
if(ret != NULL){
Py_DECREF(ret);
}
//ret crashes with non null ret
return 0;
}
#undef PyRun_String
PyAPI_FUNC(PyObject *)
PyRun_String(char *str, int s, PyObject *g, PyObject *l)
{
PyObject* r;
if(PyErr_Occurred() != NULL){
printf("WTF ERROR\n%s", PyString_AsString(PyObject_Str(PyErr_Occurred())));
PyErr_Clear();
}
r = PyRun_StringFlags(str, s, g, l, NULL);
if(r != NULL && PyBool_Check(r)){
//newer python defined a bool value but bloodlines is
//not accepting it somehow (though bool is a subclass of int)
if(r == Py_True)
return PyInt_FromLong(1L);
else
return PyInt_FromLong(0L);
}
return r;
}
Build the solution but deleted the python subprojects that don't work (they are not needed)
put this bash file on the Game/Bin directory (where the python dll lives)
cp -f /home/paulo/OS\ Images/shared/Python-2.7.1/PC/VS7.1/python27.dll ./vampire_python21.dll
cp -f /home/paulo/OS\ Images/shared/Python-2.7.1/PC/VS7.1/unicodedata.pyd ./python/unicodedata.pyd
cp -f /home/paulo/OS\ Images/shared/Python-2.7.1/PC/VS7.1/_ctypes.pyd ./python/_ctypes.pyd
cp -f /home/paulo/OS\ Images/shared/Python-2.7.1/PC/VS7.1/select.pyd ./python/select.pyd
cp -f /home/paulo/OS\ Images/shared/Python-2.7.1/PC/VS7.1/winsound.pyd ./python/winsound.pyd
cp -f /home/paulo/OS\ Images/shared/Python-2.7.1/PC/VS7.1/python.exe ./python/python.exe
cp -f /home/paulo/OS\ Images/shared/Python-2.7.1/PC/VS7.1/pythonw.exe ./python/pythonw.exe
cp -f /home/paulo/OS\ Images/shared/Python-2.7.1/PC/VS7.1/w9xpopen.exe ./python/w9xpopen.exe
rm -R ./python/Lib
cp -R /home/paulo/OS\ Images/shared/Python-2.7.1/Lib ./python/Lib
find ../ -name '*.pyc' -delete
export PYTHONVERBOSE=1; wine ../vampire.exe -console 1
compiled and ran. The game open with a console, and if you type dir(cvar)
it crashes after creating the AST during running/printing of the code (sorry wine doesn't understand the VS debug symbols). Curiously the other native pointer "dir(ccmd)" doesn't crash, but may have some clues to what is wrong with the other:
[]
Console String: __dict__, size 8
Traceback (most recent call last):
File "<string>", line 1, in <module>
NameError: name '__dict__' is not defined
Console String: __members__, size 11
Traceback (most recent call last):
File "<string>", line 1, in <module>
NameError: name '__members__' is not defined
Console String: __methods__, size 11
Traceback (most recent call last):
File "<string>", line 1, in <module>
NameError: name '__methods__' is not defined
Console String: __class__, size 9
Traceback (most recent call last):
File "<string>", line 1, in <module>
NameError: name '__class__' is not defined
Notice that it crashes BEFORE (EDIT: actually, it is being called again somehow. Exceptions in the python C api? Need to investigate. EDIT2: actually this only happens in the "dir(ccmd)" command not on "dir(cvar)", that crashes right away) the return and that this function is console specific. There may very well be more alterations i'm not aware of.
"print ccmd", "str(ccmd)" or "repr(ccmd)" on the console gives :
<cvar object at 0x0245E4A8>
and "print cvar", "str(cvar)" or "repr(cvar)" gives
<cvar object at 0x0245E4A0>
Also notice i don't know what the return of the ConsoleString
function is, but i know it is testing against 0 (NULL) on the return assembly to branch a if.
EDIT: OK, found the crashing point by applying a debbuger to attached when crashed: It is line 3963 of typeobject.c on the python 2.7.1 source,
if (base && base->tp_dict == NULL)
Base is not null, yet accessing that dictionary crashes the interpreter. Should i send a bug report?