mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-29 21:30:53 +00:00
Use pythoncapi-compat to simplify Python C API backwards compatibility
This commit is contained in:
+1114
File diff suppressed because it is too large
Load Diff
@@ -29,7 +29,8 @@
|
||||
|
||||
// must be included first
|
||||
#include <Python.h>
|
||||
#include <frameobject.h>
|
||||
|
||||
#include "3rdparty/pythoncapi_compat.h"
|
||||
|
||||
#ifdef slots_was_defined
|
||||
#define slots
|
||||
@@ -72,43 +73,6 @@ PyTypeObject **SbkPySide2_QtWidgetsTypes = NULL;
|
||||
#include "PythonContext.h"
|
||||
#include "version.h"
|
||||
|
||||
// helpers for new PyFrameObject accessors in newer python versions, that are required starting from
|
||||
// python 3.11
|
||||
#if PY_VERSION_HEX < 0x030B0000
|
||||
|
||||
// Get the frame's f_globals attribute.
|
||||
// Return a strong reference
|
||||
PyObject *PyFrame_GetGlobals(PyFrameObject *frame)
|
||||
{
|
||||
PyObject *ret = frame->f_globals;
|
||||
Py_XINCREF(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if PY_VERSION_HEX < 0x03090000
|
||||
|
||||
// Get the frame next outer frame.
|
||||
// Return a strong reference
|
||||
PyFrameObject *PyFrame_GetBack(PyFrameObject *frame)
|
||||
{
|
||||
PyFrameObject *ret = frame->f_back;
|
||||
Py_XINCREF(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Get the frame code.
|
||||
// Return a strong reference
|
||||
PyCodeObject *PyFrame_GetCode(PyFrameObject *frame)
|
||||
{
|
||||
PyCodeObject *ret = frame->f_code;
|
||||
Py_XINCREF(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// exported by generated files, used to check interface compliance
|
||||
bool CheckCoreInterface(rdcstr &log);
|
||||
bool CheckQtInterface(rdcstr &log);
|
||||
@@ -883,8 +847,7 @@ void PythonContext::ConvertPyArgs(const ExtensionCallbackData &data,
|
||||
if(!out)
|
||||
{
|
||||
qCritical() << "Couldn't convert" << in << "to python object";
|
||||
out = Py_None;
|
||||
Py_XINCREF(out);
|
||||
out = Py_XNewRef(Py_None);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1063,7 +1026,7 @@ QWidget *PythonContext::QWidgetFromPy(PyObject *widget)
|
||||
if(!initialised())
|
||||
return NULL;
|
||||
|
||||
if(widget == Py_None || widget == NULL)
|
||||
if(Py_IsNone(widget) || widget == NULL)
|
||||
return NULL;
|
||||
|
||||
if(!SbkPySide2_QtCoreTypes || !SbkPySide2_QtGuiTypes || !SbkPySide2_QtWidgetsTypes)
|
||||
@@ -1098,7 +1061,7 @@ QStringList PythonContext::completionOptions(QString base)
|
||||
{
|
||||
opt = PyObject_CallFunction(completeFunction, "si", input, idx);
|
||||
|
||||
if(opt && opt != Py_None)
|
||||
if(opt && !Py_IsNone(opt))
|
||||
{
|
||||
QString optstr = ToQStr(opt);
|
||||
|
||||
@@ -1114,7 +1077,7 @@ QStringList PythonContext::completionOptions(QString base)
|
||||
}
|
||||
|
||||
idx++;
|
||||
} while(opt && opt != Py_None);
|
||||
} while(opt && !Py_IsNone(opt));
|
||||
|
||||
// extra hack, remove the swig object functions/data but ONLY if we find a sure-fire identifier
|
||||
// (thisown) since otherwise we could remove append from a list object
|
||||
|
||||
@@ -273,8 +273,7 @@ PyObject *selfconcat_##unique_name(PyObject *self, PyObject *vals)
|
||||
if(ret)
|
||||
{
|
||||
Py_DECREF(ret);
|
||||
Py_INCREF(self);
|
||||
return self;
|
||||
return Py_NewRef(self);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
@@ -292,8 +291,7 @@ PyObject *selfrepeat_##unique_name(PyObject *self, Py_ssize_t count)
|
||||
if(ret)
|
||||
{
|
||||
Py_DECREF(ret);
|
||||
Py_INCREF(self);
|
||||
return self;
|
||||
return Py_NewRef(self);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
%feature("python:tp_str") ResultDetails "result_str";
|
||||
%feature("python:tp_repr") ResultDetails "result_str";
|
||||
|
||||
@@ -18,7 +17,7 @@ PyObject *__lt__(PyObject *other)
|
||||
void *resptr = NULL;
|
||||
ResourceId *id = NULL;
|
||||
|
||||
if(other && other != Py_None)
|
||||
if(other && !Py_IsNone(other))
|
||||
{
|
||||
int res = SWIG_ConvertPtr(other, &resptr, SWIGTYPE_p_ResourceId, 0);
|
||||
if (!SWIG_IsOK(res)) {
|
||||
@@ -125,7 +124,7 @@ PyObject *__eq__(PyObject *other)
|
||||
void *resptr = NULL;
|
||||
Class *id = NULL;
|
||||
|
||||
if(other && other != Py_None)
|
||||
if(other && !Py_IsNone(other))
|
||||
{
|
||||
int res = SWIG_ConvertPtr(other, &resptr, SWIGTYPE_p_##Class, 0);
|
||||
if (!SWIG_IsOK(res)) {
|
||||
@@ -148,7 +147,7 @@ PyObject *__ne__(PyObject *other)
|
||||
void *resptr = NULL;
|
||||
Class *id = NULL;
|
||||
|
||||
if(other && other != Py_None)
|
||||
if(other && !Py_IsNone(other))
|
||||
{
|
||||
int res = SWIG_ConvertPtr(other, &resptr, SWIGTYPE_p_##Class, 0);
|
||||
if (!SWIG_IsOK(res)) {
|
||||
@@ -202,4 +201,4 @@ DEFINE_SAFE_EQUALITY(ColorBlend)
|
||||
DEFINE_SAFE_EQUALITY(BoundVBuffer)
|
||||
DEFINE_SAFE_EQUALITY(VertexInputAttribute)
|
||||
DEFINE_SAFE_EQUALITY(BoundResource)
|
||||
DEFINE_SAFE_EQUALITY(BoundResourceArray)
|
||||
DEFINE_SAFE_EQUALITY(BoundResourceArray)
|
||||
|
||||
@@ -38,7 +38,7 @@ static int typeName##_init(PyObject *self, PyObject *args)
|
||||
|
||||
PyObject *resultobj = SWIG_NewPointerObj((void *)result, SWIGTYPE_p_##typeName, SWIG_BUILTIN_INIT);
|
||||
|
||||
if(resultobj == Py_None)
|
||||
if(Py_IsNone(resultobj))
|
||||
{
|
||||
delete result;
|
||||
return -1;
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "3rdparty/pythoncapi_compat.h"
|
||||
|
||||
// this is defined elsewhere for managing the opaque global_handle object
|
||||
extern "C" PyThreadState *GetExecutingThreadState(PyObject *global_handle);
|
||||
extern "C" PyObject *GetCurrentGlobalHandle();
|
||||
@@ -178,11 +180,7 @@ inline void get_return(const char *funcname, PyObject *result, PyObject *global_
|
||||
struct PyObjectRefCounter
|
||||
{
|
||||
PyObjectRefCounter(PyObject *o) : obj(o) { Py_INCREF(obj); }
|
||||
PyObjectRefCounter(const PyObjectRefCounter &o)
|
||||
{
|
||||
obj = o.obj;
|
||||
Py_INCREF(obj);
|
||||
}
|
||||
PyObjectRefCounter(const PyObjectRefCounter &o) { obj = Py_NewRef(o.obj); }
|
||||
~PyObjectRefCounter()
|
||||
{
|
||||
// it may not be safe at the point this is destroyed to decref the object. For example if a
|
||||
@@ -269,8 +267,7 @@ struct ScopedFuncCall
|
||||
{
|
||||
ScopedFuncCall(PyObject *h)
|
||||
{
|
||||
handle = h;
|
||||
Py_XINCREF(handle);
|
||||
handle = Py_XNewRef(h);
|
||||
gil = PyGILState_Ensure();
|
||||
}
|
||||
|
||||
@@ -288,7 +285,7 @@ template <typename funcType>
|
||||
funcType ConvertFunc(const char *funcname, PyObject *func, ExceptionHandler exHandle)
|
||||
{
|
||||
// allow None to indicate no callback
|
||||
if(func == Py_None)
|
||||
if(Py_IsNone(func))
|
||||
return funcType();
|
||||
|
||||
// add a reference to the global object so it stays alive while we execute, in case this is an
|
||||
|
||||
@@ -208,7 +208,7 @@ inline bool check_interface(rdcstr &log, swig_type_info **swig_types, size_t num
|
||||
}
|
||||
|
||||
// if it's a callable it's a method, ignore it
|
||||
if(!PyCallable_Check(value) && !PyType_IsSubtype(value->ob_type, &PyStaticMethod_Type))
|
||||
if(!PyCallable_Check(value) && !PyType_IsSubtype(Py_TYPE(value), &PyStaticMethod_Type))
|
||||
{
|
||||
// some hardcoded exclusions that we allow to break the naming scheme
|
||||
if(typeName == "KnownShaderTool")
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include <map>
|
||||
#include <type_traits>
|
||||
|
||||
#include "3rdparty/pythoncapi_compat.h"
|
||||
|
||||
// struct to allow partial specialisation for enums
|
||||
template <typename T, bool isEnum = std::is_enum<T>::value>
|
||||
struct TypeConversion
|
||||
@@ -79,17 +81,12 @@ struct TypeConversion<PyObject *, false>
|
||||
{
|
||||
static int ConvertFromPy(PyObject *in, PyObject *&out)
|
||||
{
|
||||
out = in;
|
||||
Py_XINCREF(out);
|
||||
out = Py_XNewRef(in);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static PyObject *ConvertToPy(PyObject *in)
|
||||
{
|
||||
Py_XINCREF(in);
|
||||
return in;
|
||||
}
|
||||
static PyObject *ConvertToPy(PyObject *in) { return Py_XNewRef(in); }
|
||||
};
|
||||
|
||||
// specialisations for pointer types (opaque handles to be moved not copied)
|
||||
@@ -143,7 +140,7 @@ struct TypeConversion<bool, false>
|
||||
if(!PyBool_Check(in))
|
||||
return SWIG_TypeError;
|
||||
|
||||
if(in == Py_True)
|
||||
if(Py_IsTrue(in))
|
||||
out = true;
|
||||
else
|
||||
out = false;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
%module(docstring="This is the API to QRenderDoc's high-level UI panels and functionality.") qrenderdoc
|
||||
|
||||
%feature("autodoc", "0");
|
||||
@@ -8,6 +9,10 @@
|
||||
#define DOCUMENT3(text1, text2, text3) %feature("docstring") text1 text2 text3
|
||||
#define DOCUMENT4(text1, text2, text3, text4) %feature("docstring") text1 text2 text3 text4
|
||||
|
||||
%header %{
|
||||
#include "3rdparty/pythoncapi_compat.h"
|
||||
%}
|
||||
|
||||
%begin %{
|
||||
#undef slots
|
||||
|
||||
@@ -51,11 +56,11 @@ TEMPLATE_FIXEDARRAY_DECLARE(rdcfixedarray);
|
||||
%}
|
||||
|
||||
%typemap(in) QWidget * {
|
||||
if($input == Py_None)
|
||||
if(Py_IsNone($input))
|
||||
$1 = NULL;
|
||||
else
|
||||
$1 = QWidgetFromPy($input);
|
||||
if($input && $input != Py_None && !$1)
|
||||
if($input && !Py_IsNone($input) && !$1)
|
||||
{
|
||||
SWIG_exception_fail(SWIG_TypeError, "in method '$symname' QWidget expected for argument $argnum of type '$1_basetype'");
|
||||
}
|
||||
@@ -125,7 +130,7 @@ TEMPLATE_FIXEDARRAY_DECLARE(rdcfixedarray);
|
||||
|
||||
result = new PythonCaptureViewer(self);
|
||||
resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_ICaptureViewer, SWIG_BUILTIN_INIT | 0);
|
||||
return resultobj == Py_None ? -1 : 0;
|
||||
return Py_IsNone(resultobj) ? -1 : 0;
|
||||
}
|
||||
|
||||
SWIGINTERN PyObject *capviewer_deinit(PyObject *self, PyObject *args)
|
||||
@@ -260,4 +265,4 @@ QWidget *UnwrapBareQWidget(PyObject *obj)
|
||||
return ret;
|
||||
}
|
||||
|
||||
%}
|
||||
%}
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
#define DOCUMENT3(text1, text2, text3) %feature("docstring") text1 text2 text3
|
||||
#define DOCUMENT4(text1, text2, text3, text4) %feature("docstring") text1 text2 text3 text4
|
||||
|
||||
%header %{
|
||||
#include "3rdparty/pythoncapi_compat.h"
|
||||
%}
|
||||
|
||||
// include header for typed enums (hopefully using PEP435 enums)
|
||||
%include <enums.swg>
|
||||
|
||||
@@ -470,9 +474,9 @@ extern "C" PyObject *RENDERDOC_DumpObject(PyObject *obj)
|
||||
void *resptr = NULL;
|
||||
|
||||
// for basic types, return the repr directly
|
||||
if(obj == Py_True ||
|
||||
obj == Py_False ||
|
||||
obj == Py_None ||
|
||||
if(Py_IsTrue(obj) ||
|
||||
Py_IsFalse(obj) ||
|
||||
Py_IsNone(obj) ||
|
||||
PyObject_IsInstance(obj, (PyObject*)&PyFloat_Type) ||
|
||||
PyObject_IsInstance(obj, (PyObject*)&PyLong_Type) ||
|
||||
PyObject_IsInstance(obj, (PyObject*)&PyBytes_Type) ||
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "3rdparty/pythoncapi_compat.h"
|
||||
|
||||
template <typename objType>
|
||||
inline std::map<const objType *, PyObject *> &obj2py();
|
||||
|
||||
@@ -263,7 +265,7 @@ struct TypeConversion<StructuredBufferList, false>
|
||||
for(int i = 0; i < out.count(); i++)
|
||||
{
|
||||
PyObject *elem = PyList_GetItem(in, i);
|
||||
if(elem == Py_None)
|
||||
if(Py_IsNone(elem))
|
||||
{
|
||||
out[i] = NULL;
|
||||
}
|
||||
@@ -389,7 +391,7 @@ struct TypeConversion<StructuredObjectList, false>
|
||||
for(int i = 0; i < out.count(); i++)
|
||||
{
|
||||
PyObject *elem = PyList_GetItem(in, i);
|
||||
if(elem == Py_None)
|
||||
if(Py_IsNone(elem))
|
||||
{
|
||||
out[i] = NULL;
|
||||
}
|
||||
@@ -535,7 +537,7 @@ struct TypeConversion<StructuredChunkList, false>
|
||||
for(int i = 0; i < out.count(); i++)
|
||||
{
|
||||
PyObject *elem = PyList_GetItem(in, i);
|
||||
if(elem == Py_None)
|
||||
if(Py_IsNone(elem))
|
||||
{
|
||||
out[i] = NULL;
|
||||
}
|
||||
|
||||
@@ -399,6 +399,10 @@ HEADERS += 3rdparty/toolwindowmanager/ToolWindowManager.h \
|
||||
SOURCES += 3rdparty/flowlayout/FlowLayout.cpp
|
||||
HEADERS += 3rdparty/flowlayout/FlowLayout.h
|
||||
|
||||
# Add pythoncapi-compat
|
||||
|
||||
HEADERS += 3rdparty/pythoncapi_compat.h
|
||||
|
||||
# Add Scintilla last as it has extra search paths
|
||||
|
||||
# Needed for building
|
||||
|
||||
Reference in New Issue
Block a user