Редактирование завершено: я обертываю пользовательскую библиотеку Python с целью в конечном итоге удалить пользовательский код и использовать недавний Python вместо старой версии, которая используется сейчас.Одна из функций инициализирует расширение Python и вызывает
PyObject* _PyObject_New(PyTypeObject *type)
В моей оболочке объект (c), созданный этим вызовом, падает на PyErr_Print()
(да, я тоже обернул его).
Я бы хотел поэкспериментировать с заменой вызовов Repr или Str на что-нибудь по моему выбору, чтобы увидеть, виновны ли они.Кроме того, я не могу использовать капсулы, потому что объекты должны быть доступны даже в коде Python.
По запросу: настоящая проблема происходит везде, где вызывается один из двух собственных указателей c.Я взял исходный код Python 2.7.1, открытый на VS 2003 (проект на PC / VS7.1), открыл там pythonrun.c
и добавил в конце заглушки функций тройки:
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;
}
Сборкарешение, но удалил подпроекты python, которые не работают (они не нужны)
поместите этот файл bash в каталог Game / Bin (где живет python)
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
скомпилировано и запущено.Игра открывается с консоли, и если вы набираете dir(cvar)
, она вылетает после создания AST во время выполнения / печати кода (извините, wine не понимает символы отладки VS).Любопытно, что другой родной указатель "dir (ccmd)" не падает, но может иметь некоторые подсказки, что не так с другим:
[]
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
Обратите внимание, что он падает до (EDIT: на самом деле, этовызывается снова как-то. Исключения в Python C API? Нужно исследовать. EDIT2: на самом деле это происходит только в команде "dir (ccmd)", а не в "dir (cvar)", который вылетает сразу) return и что этофункция зависит от консоли.Вполне возможно, что будет больше изменений, о которых я не знаю.
"print ccmd", "str (ccmd)" или "repr (ccmd)" на консоли дает:
<cvar object at 0x0245E4A8>
и "print cvar", "str (cvar)" или "repr (cvar)" дают
<cvar object at 0x0245E4A0>
Также обратите внимание, что я не знаю, что такое возвращение функции ConsoleString
, ноя знаю, что это тестирование против 0 (NULL) на возвращаемой сборке, чтобы разветвить, если.
РЕДАКТИРОВАТЬ: ОК, нашел точку сбоя, применяя отладчик к присоединенному при падении: Это строка 3963 из typeobject.cв источнике Python 2.7.1
if (base && base->tp_dict == NULL)
Base не равен null, но доступ к этому словарю приводит к сбою интерпретатора.Должен ли я отправить отчет об ошибке?