Расширения 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 для компиляции этого файла.
2 ответа
Примечания:
- Я говорю о Python2.7 здесь (так как в более новых версиях
subprocess
модуль больше не имеет собственной реализации C для Win) - Python2.7 построен (официально) с использованием VStudio2008 (9.0) в соответствии с https://wiki.python.org/moin/WindowsCompilers. Сборка с более новой (или лучше: другой) версией может привести к некоторым другим (и труднее найти) ошибкам. Например, когда я собрал его с помощью VStudio2010 (10.0) (я использовал собранную версию для запуска сложного набора (.py *) сценариев), у меня возникли некоторые проблемы во время выполнения при обнаружении ошибок, связанных с сокетом, из-за некоторых несоответствий между
errno
а такжеWSA*
коды, которые были изменены между двумя версиями
Когда я тестировал, я не мог понять, почему вы столкнулись с проблемой, и я не стал, потом какое-то время я забыл об этом, потом, когда вы опубликовали последний комментарий, он снова начал пожирать меня живьем. Как я уже сказал, я смог успешно скомпилировать файл, используя VStudio2010 и 2013.
Попытка скомпилировать один и тот же (это было только предположение) код с разными результатами -> способ компиляции кода может отличаться. Поэтому я начал исследовать другие возможные места для определения staticforward
а также statichere
(кроме строк 878/879 объекта.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 проектов, автоматически конвертируемых VStudio из тех, что находятся в папке PCbuild):
VStudio2013
/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"
VStudio2010
/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++ (флаг [MSDN]: /Tc, /Tp, /TC, /TP (указать тип исходного файла)). Конечно, компиляция _subprocess.c под C++ приведет к появлению ошибки.
Отметьте [SO]: создание динамически размещаемой структуры с двухмерной динамически размещаемой строкой (ответ @CristiFati), для (немного) большего количества деталей и того, как одна и та же ошибка вызвала очень разные ошибки.
Хорошо, я нашел ответ.
Оказывается, что определение staticforward
должно было extern
вместо static
, Мой компилятор не знал, как с этим справиться. Я думаю, в других компиляторах это работает нормально.