Любой способ вызова кода C / C ++ из Python без изменения кода C / C ++? - PullRequest
4 голосов
/ 08 марта 2011

Редактирование завершено: я обертываю пользовательскую библиотеку 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, но доступ к этому словарю приводит к сбою интерпретатора.Должен ли я отправить отчет об ошибке?

...