Расширения Python с C: staticforward

Поэтому мне нужно было использовать код модуля подпроцесса, чтобы добавить некоторые необходимые мне функции. Когда я пытался скомпилировать файл _subprocess.c, он выдает следующее сообщение об ошибке:

Error 1 error C2086: 'PyTypeObject sp_handle_type' : redefinition

Это часть кода, относящаяся к файлу _subprocess.c:

typedef struct {
    PyObject_HEAD
    HANDLE handle;
} sp_handle_object;

staticforward PyTypeObject sp_handle_type;

static PyObject*
sp_handle_new(HANDLE handle)
{
    sp_handle_object* self;

    self = PyObject_NEW(sp_handle_object, &sp_handle_type);
    if (self == NULL)
        return NULL;

    self->handle = handle;

    return (PyObject*)self;
}

#if defined(MS_WIN32) && !defined(MS_WIN64)
#define HANDLE_TO_PYNUM(handle) PyInt_FromLong((long) handle)
#define PY_HANDLE_PARAM "l"
#else
#define HANDLE_TO_PYNUM(handle) PyLong_FromLongLong((long long) handle)
#define PY_HANDLE_PARAM "L"
#endif

static PyObject*
sp_handle_detach(sp_handle_object* self, PyObject* args)
{
    HANDLE handle;

    if (!PyArg_ParseTuple(args, ":Detach"))
        return NULL;

    handle = self->handle;

    self->handle = INVALID_HANDLE_VALUE;

    /* note: return the current handle, as an integer */
    return HANDLE_TO_PYNUM(handle);
}

static PyObject*
sp_handle_close(sp_handle_object* self, PyObject* args)
{
    if (!PyArg_ParseTuple(args, ":Close"))
        return NULL;

    if (self->handle != INVALID_HANDLE_VALUE) {
        CloseHandle(self->handle);
        self->handle = INVALID_HANDLE_VALUE;
    }
    Py_INCREF(Py_None);
    return Py_None;
}

static void
sp_handle_dealloc(sp_handle_object* self)
{
    if (self->handle != INVALID_HANDLE_VALUE)
        CloseHandle(self->handle);
    PyObject_FREE(self);
}

static PyMethodDef sp_handle_methods[] = {
    { "Detach", (PyCFunction)sp_handle_detach, METH_VARARGS },
    { "Close", (PyCFunction)sp_handle_close, METH_VARARGS },
    { NULL, NULL }
};

static PyObject*
sp_handle_getattr(sp_handle_object* self, char* name)
{
    return Py_FindMethod(sp_handle_methods, (PyObject*)self, name);
}

static PyObject*
sp_handle_as_int(sp_handle_object* self)
{
    return HANDLE_TO_PYNUM(self->handle);
}

static PyNumberMethods sp_handle_as_number;

statichere PyTypeObject sp_handle_type = {
    PyObject_HEAD_INIT(NULL)
    0,                                  /*ob_size*/
    "_subprocess_handle", sizeof(sp_handle_object), 0,
    (destructor)sp_handle_dealloc, /*tp_dealloc*/
    0, /*tp_print*/
    (getattrfunc)sp_handle_getattr,/*tp_getattr*/
    0,                                  /*tp_setattr*/
    0,                                  /*tp_compare*/
    0,                                  /*tp_repr*/
    &sp_handle_as_number,               /*tp_as_number */
    0,                                  /*tp_as_sequence */
    0,                                  /*tp_as_mapping */
    0                                   /*tp_hash*/
};`

Также я обнаружил, что:

#define staticforward static
#define statichere static

Я не понимаю, что я делаю неправильно. Любая помощь будет оценена по достоинству. Кстати (я не уверен, что это актуально), я использую Visual Studio Professional 2013 для компиляции этого файла.


person Omer    schedule 25.01.2017    source источник


Ответы (2)


Примечания:

  • Я говорю о Python 2.7 здесь (поскольку в более новых версиях модуль subprocess больше не имеет собственной реализации C для Win )
  • Python 2.7 построен (официально) с использованием VStudio2008 (9.0) в соответствии с [Python.Wiki]: WindowsCompilers. Создание его с более новой (или лучше: другой) версией может привести к некоторым другим (и труднее найти) ошибкам. Например, когда я собирал его с помощью VStudio 2010 (10.0) (я использовал встроенную версию для запуска сложного набора скриптов (.py*), у меня были некоторые проблемы во время выполнения при обнаружении ошибок, связанных с сокетом, из-за некоторых несоответствий между кодами errno и WSA*, которые были изменены между двумя версиями

Когда я тестировал, я не мог понять, почему вы столкнулись с проблемой, а я нет, потом на какое-то время я забыл об этом, затем, когда вы разместили последний комментарий, он снова начал пожирать меня заживо. Как я уже сказал, мне удалось успешно скомпилировать файл с помощью VStudio 2010/2013.

Попытка скомпилировать один и тот же (это было только предположение) код с разными результатами -> способ компиляции кода может отличаться. Поэтому я начал искать другие возможные места определения для staticforward и statichere (кроме строк 878 / 879 из < em>object.h) из-за условных макросов: #if, #ifdef, . .. . Но я не мог найти ни одного. Итак, я добавил несколько более простых утверждений:

staticforward int i;
statichere int i = 2;

затем я вручную заменил определения:

static int i;
static int i = 2;

в _subprocess.c (по стечению обстоятельств я добавил их в строке #137 — как раз перед statichere PyTypeObject sp_handle_type = { — что помешало мне разобраться в проблеме на этом этапе), и это еще компилируется!!!

Следующим шагом я вставил приведенные выше строки в другое открытое решение (в исходный файл .cpp), и мне удалось воспроизвести ошибку. Поэтому я уделил больше внимания флагам компилятора (скопировал/вставил из настроек x86 Debug проектов, автоматически преобразованных VStudio из найденных в папка PCbuild):

  • VStudio 2013

    /GS
    /analyze-
    /W3
    /Gy
    /Zc:wchar_t
    /I"E:\Work\Dev\Fati\WinBuild\OPSWpython27\src\Python-2.7.11-vs2k13\Python"
    /I"E:\Work\Dev\Fati\WinBuild\OPSWpython27\src\Python-2.7.11-vs2k13\Modules\zlib"
    /I"E:\Work\Dev\Fati\WinBuild\OPSWpython27\src\Python-2.7.11-vs2k13\Include"
    /I"E:\Work\Dev\Fati\WinBuild\OPSWpython27\src\Python-2.7.11-vs2k13\PC"
    /Zi
    /Gm-
    /Od
    /Fd"E:\Work\Dev\Fati\WinBuild\OPSWpython27\src\Python-2.7.11-vs2k13\PCbuild\obj\win32_Debug\pythoncore\vc120.pdb"
    /fp:precise
    /D "_USRDLL"
    /D "Py_BUILD_CORE"
    /D "Py_ENABLE_SHARED"
    /D "MS_DLL_ID=\"2.7-32\""
    /D "WIN32"
    /D "_WIN32"
    /D "_DEBUG"
    /D "_WINDLL"
    /errorReport:prompt
    /GF
    /WX-
    /Zc:forScope
    /Gd
    /Oy-
    /Oi
    /MDd
    /Fa"E:\Work\Dev\Fati\WinBuild\OPSWpython27\src\Python-2.7.11-vs2k13\PCbuild\obj\win32_Debug\pythoncore\"
    /nologo
    /Fo"E:\Work\Dev\Fati\WinBuild\OPSWpython27\src\Python-2.7.11-vs2k13\PCbuild\obj\win32_Debug\pythoncore\"
    /Fp"E:\Work\Dev\Fati\WinBuild\OPSWpython27\src\Python-2.7.11-vs2k13\PCbuild\obj\win32_Debug\pythoncore\python27_d.pch"
    
  • VStudio 2010

    /I"..\Python"
    /I"..\Modules\zlib"
    /I"..\Include"
    /I"..\PC"
    /Zi
    /nologo
    /W3
    /WX-
    /Od
    /Oy-
    /D "_USRDLL"
    /D "Py_BUILD_CORE"
    /D "Py_ENABLE_SHARED"
    /D "WIN32"
    /D "_DEBUG"
    /D "_WIN32"
    /D "_WINDLL"
    /GF
    /Gm-
    /MDd
    /GS
    /Gy
    /fp:precise
    /Zc:wchar_t
    /Zc:forScope
    /Fp"E:\Work\Dev\Fati\WinBuild\OPSWpython27\src\Python-2.7.10-vcbuild\PCbuild\Win32-temp-Debug\pythoncore\pythoncore.pch"
    /Fa"E:\Work\Dev\Fati\WinBuild\OPSWpython27\src\Python-2.7.10-vcbuild\PCbuild\Win32-temp-Debug\pythoncore\"
    /Fo"E:\Work\Dev\Fati\WinBuild\OPSWpython27\src\Python-2.7.10-vcbuild\PCbuild\Win32-temp-Debug\pythoncore\"
    /Fd"E:\Work\Dev\Fati\WinBuild\OPSWpython27\src\Python-2.7.10-vcbuild\PCbuild\Win32-temp-Debug\pythoncore\vc100.pdb"
    /Gd
    /analyze-
    /errorReport:queue
    

а потом меня осенило: это способ компиляции файла: C против C++ ([MS.Docs]: /Tc, / Tp, /TC, /TP (указать тип исходного файла) флаг). Конечно, компиляция _subprocess.c как C++ выдаст вашу ошибку.

Проверьте [SO]: Создание динамически выделенная структура с 2D-динамически выделенной строкой (@ответ CristiFati), для (немного) более подробной информации и того, как одна и та же ошибка вызывает очень разные ошибки.

person CristiFati    schedule 14.03.2017
comment
Это можно считать ответом на ваш вопрос? - person CristiFati; 24.01.2018

Хорошо, я нашел ответ.

Оказывается, определение staticforward должно было быть extern вместо static. Мой компилятор не знал, как с этим справиться. Я думаю, в других компиляторах это работает нормально.

person Omer    schedule 26.01.2017
comment
Этот файл (как и все остальные) должен компилироваться OOTB. Я пробовал несколько комбинаций (например, VC2k10 и Py27), но не смог воспроизвести проблему. Вероятно, вам следует (ищите дубликаты) и закрыть вопрос. В любом случае, я не вижу в этом решения. - person CristiFati; 27.01.2017
comment
В Visual Studio 2013 нельзя дважды определить статическую переменную. staticforward и statichere были определены как статические, поэтому на самом деле ошибка является законной. Изменение staticforward на extern сообщает компилятору, что переменная будет определена позже. - person Omer; 01.02.2017
comment
В Visual Studio 2013 нельзя дважды определить статическую переменную. staticforward и statichere были защищены как «статические», поэтому на самом деле ошибка действительна. Это не может быть более неправильным. В любой версии компилятора VStudio (или любой VS или C) static означает, что переменные видны только в блоке компиляции (c / c++ файл). Пожалуйста, проверьте Интернет (Google, MSDN, Wiki,... и множество других) для деталей. - person CristiFati; 03.02.2017
comment
Это немного абсурдно, что (вы так думаете) целое сообщество сделало такую ​​ошибку (назвав staticforward(staic), но имея в виду extern), и в 2017 году ты был тем, кто ее нашел. Кстати, на моем компьютере Py2.7.10 компилирует OOTB с использованием VS2k13.... теперь вопрос: что вы сделали для subprocess.c (или один из включенных заголовков), чтобы так все испортить? - person CristiFati; 03.02.2017
comment
Что вы действительно пытались сделать? - person CristiFati; 10.03.2017
comment
@CristiFati Я расширил модуль подпроцесса для поддержки процессов порождения с заданным узлом NUMA и маской сходства (например, в команде «Пуск» Windows). - person Omer; 11.03.2017