Replace fixed C arrays with wrapper class in public interface

* These map more naturally to python tuples and are easier to wrap in and out.
* We also tidy up the FloatVecVal etc and standardise the members of
  ShaderValue.
This commit is contained in:
baldurk
2020-12-09 18:16:08 +00:00
parent 580f96c8a1
commit 7ff7e0a71d
66 changed files with 1833 additions and 1459 deletions
@@ -406,3 +406,88 @@ void ARRAY_INSTANTIATION_CHECK_NAME(arrayType)(arrayType<nspace::innerType> *)
%}
%enddef
/////////////////////////////////////////////////////////////////////////
// Similar to above for handling templated container, but for fixed array
// it's simpler because we map it to a tuple. Since tuples are immutable
// we only need conversion in and out
%define TEMPLATE_FIXEDARRAY_DECLARE(typeName)
%typemap(in) const typeName & {
static_assert(false, "Error! Should not use this typemap");
}
%typemap(in) typeName {
static_assert(false, "Error! Should not use this typemap");
}
%typemap(in) typeName * (unsigned char tempmem[16*8]) {
using array_type = std::remove_pointer<decltype($1)>::type;
{
tempalloc($1, tempmem);
int failIdx = 0;
int res = TypeConversion<array_type>::ConvertFromPy($input, indirect($1), &failIdx);
if(!SWIG_IsOK(res))
{
if(res == SWIG_TypeError)
{
SWIG_exception_fail(SWIG_ArgError(res), "in method '$symname' argument $argnum of type '$1_basetype'");
}
else
{
snprintf(convert_error, sizeof(convert_error)-1, "in method '$symname' argument $argnum of type '$1_basetype', decoding element %d", failIdx);
SWIG_exception_fail(SWIG_ArgError(res), convert_error);
}
}
}
}
%typemap(out) typeName {
$result = ConvertToPy(indirect($1));
}
%typemap(out) typeName * {
$result = ConvertToPy(indirect($1));
}
// add a check to make sure that we explicitly instantiate all uses of this template (as a reference
// type, not as a purely in parameter to a function - those are converted by value to C++ to allow
// passing pure lists that aren't C++ side at all).
%header %{
template<typename innerType, size_t N>
void ARRAY_INSTANTIATION_CHECK_NAME(typeName)(typeName<innerType, N> *);
%}
// override these typemaps to instantiate a checking template.
%typemap(check) typeName * { ARRAY_INSTANTIATION_CHECK_NAME(typeName)($1); }
%typemap(check) typeName & { ARRAY_INSTANTIATION_CHECK_NAME(typeName)($1); }
%typemap(check) typeName { ARRAY_INSTANTIATION_CHECK_NAME(typeName)($1); }
%typemap(ret) typeName * { ARRAY_INSTANTIATION_CHECK_NAME(typeName)($1); }
%typemap(ret) typeName & { ARRAY_INSTANTIATION_CHECK_NAME(typeName)($1); }
%typemap(ret) typeName { ARRAY_INSTANTIATION_CHECK_NAME(typeName)(&$1); }
%enddef
%define TEMPLATE_FIXEDARRAY_INSTANTIATE(arrayType, innerType, size)
// instantiate template
%rename(arrayType##_of_##size##_##innerType) arrayType<innerType, size>;
%template(arrayType##_of_##size##_##innerType) arrayType<innerType, size>;
%header %{
template<>
void ARRAY_INSTANTIATION_CHECK_NAME(arrayType)(arrayType<innerType, size> *)
{
}
%}
%enddef
@@ -602,6 +602,80 @@ struct TypeConversion<rdcarray<U>, false>
static PyObject *ConvertToPy(const rdcarray<U> &in) { return ConvertToPy(in, NULL); }
};
template <typename U, size_t N>
struct TypeConversion<rdcfixedarray<U, N>, false>
{
static swig_type_info *GetTypeInfo()
{
static swig_type_info *cached_type_info = NULL;
static rdcstr typeName = "rdcfixedarray < " + TypeName<U>() + "," + ToStr((uint32_t)N) + " > *";
if(cached_type_info)
return cached_type_info;
cached_type_info = SWIG_TypeQuery(typeName.c_str());
return cached_type_info;
}
// we add some extra parameters so the typemaps for array can use these to get
// nicer failure error messages out with the index that failed
static int ConvertFromPy(PyObject *in, rdcfixedarray<U, N> &out, int *failIdx)
{
if(!PySequence_Check(in))
return SWIG_TypeError;
Py_ssize_t size = PySequence_Size(in);
if(size != N)
return SWIG_TypeError;
for(size_t i = 0; i < N; i++)
{
int ret = TypeConversion<U>::ConvertFromPy(PySequence_GetItem(in, i), out[i]);
if(!SWIG_IsOK(ret))
{
if(failIdx)
*failIdx = (int)i;
return ret;
}
}
return SWIG_OK;
}
static int ConvertFromPy(PyObject *in, rdcfixedarray<U, N> &out)
{
return ConvertFromPy(in, out, NULL);
}
static PyObject *ConvertToPy(const rdcfixedarray<U, N> &in, int *failIdx)
{
PyObject *ret = PyTuple_New(N);
if(!ret)
return NULL;
for(size_t i = 0; i < N; i++)
{
PyObject *obj = TypeConversion<U>::ConvertToPy(in[i]);
if(!obj)
{
if(failIdx)
*failIdx = 0;
Py_XDECREF(ret);
return NULL;
}
PyTuple_SetItem(ret, i, obj);
}
return ret;
}
static PyObject *ConvertToPy(const rdcfixedarray<U, N> &in) { return ConvertToPy(in, NULL); }
};
// specialisation for string
template <>
struct TypeConversion<rdcstr, false>
@@ -2,57 +2,6 @@
%define STRINGIZE(val) #val %enddef
///////////////////////////////////////////////////////////////////////////////////////////////
// typemaps for more sensible fixed-array handling, based on typemaps from SWIG documentation
%define FIXED_ARRAY_TYPEMAPS(BaseType)
%typemap(out) BaseType [ANY] {
$result = PyList_New($1_dim0);
for(int i = 0; i < $1_dim0; i++)
{
PyObject *o = TypeConversion<BaseType>::ConvertToPy( $1[i]);
if(!o)
{
snprintf(convert_error, sizeof(convert_error)-1, "in method '$symname' returning type '$1_basetype', encoding element %d", i);
SWIG_exception_fail(SWIG_ValueError, convert_error);
}
PyList_SetItem($result,i,o);
}
}
%typemap(arginit) BaseType [ANY] {
$1 = NULL;
}
%typemap(in) BaseType [ANY] {
if(!PySequence_Check($input))
{
SWIG_exception_fail(SWIG_TypeError, "in method '$symname' argument $argnum of type '$1_basetype'. Expected sequence");
}
if(PySequence_Length($input) != $1_dim0) {
SWIG_exception_fail(SWIG_ValueError, "in method '$symname' argument $argnum of type '$1_basetype'. Expected $1_dim0 elements");
}
$1 = new BaseType[$1_dim0];
for(int i = 0; i < $1_dim0; i++) {
PyObject *o = PySequence_GetItem($input,i);
int res = TypeConversion<BaseType>::ConvertFromPy(o, $1[i]);
if(!SWIG_IsOK(res))
{
snprintf(convert_error, sizeof(convert_error)-1, "in method '$symname' argument $argnum of type '$1_basetype', decoding element %d", i);
SWIG_exception_fail(SWIG_ArgError(res), convert_error);
}
}
}
%typemap(freearg) BaseType [ANY] {
delete[] $1;
}
%enddef
///////////////////////////////////////////////////////////////////////////////////////////////
// simple typemaps for an object that's converted directly by-value. This is perfect for python
// immutable objects like strings or datetimes
+1
View File
@@ -31,6 +31,7 @@
%import "renderdoc.i"
TEMPLATE_ARRAY_DECLARE(rdcarray);
TEMPLATE_FIXEDARRAY_DECLARE(rdcfixedarray);
// pass QWidget objects to PySide
%{
+25 -13
View File
@@ -87,6 +87,8 @@
%ignore rdcdatetime;
%ignore rdcstr;
%ignore rdcinflexiblestr;
%ignore rdcfixedarray;
%ignore rdcfixedarray::operator[];
%ignore rdcliteral;
%ignore rdcpair;
%ignore bytebuf;
@@ -198,19 +200,6 @@ SIMPLE_TYPEMAPS(rdcinflexiblestr)
SIMPLE_TYPEMAPS(rdcdatetime)
SIMPLE_TYPEMAPS(bytebuf)
FIXED_ARRAY_TYPEMAPS(ResourceId)
FIXED_ARRAY_TYPEMAPS(double)
FIXED_ARRAY_TYPEMAPS(float)
FIXED_ARRAY_TYPEMAPS(bool)
FIXED_ARRAY_TYPEMAPS(uint64_t)
FIXED_ARRAY_TYPEMAPS(int64_t)
FIXED_ARRAY_TYPEMAPS(uint32_t)
FIXED_ARRAY_TYPEMAPS(int32_t)
FIXED_ARRAY_TYPEMAPS(uint16_t)
FIXED_ARRAY_TYPEMAPS(int16_t)
FIXED_ARRAY_TYPEMAPS(uint8_t)
FIXED_ARRAY_TYPEMAPS(int8_t)
REFCOUNTED_TYPE(SDChunk);
REFCOUNTED_TYPE(SDObject);
@@ -229,6 +218,7 @@ NON_TEMPLATE_ARRAY_INSTANTIATE(StructuredBufferList)
// these types are to be treated like python lists/arrays, and will be instantiated after declaration
// below
TEMPLATE_ARRAY_DECLARE(rdcarray);
TEMPLATE_FIXEDARRAY_DECLARE(rdcfixedarray);
///////////////////////////////////////////////////////////////////////////////////////////
// Actually include header files here. Note that swig is configured not to recurse, so we
@@ -319,6 +309,28 @@ EXTEND_ARRAY_CLASS_METHODS(StructuredChunkList)
EXTEND_ARRAY_CLASS_METHODS(StructuredObjectList)
EXTEND_ARRAY_CLASS_METHODS(StructuredBufferList)
// If you get an error with add_your_use_of_rdcfixedarray_to_swig_interface missing, add your type here
// or in qrenderdoc.i, depending on which one is appropriate
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, float, 2)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, float, 4)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, uint32_t, 3)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, uint32_t, 4)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, uint64_t, 4)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, int32_t, 4)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, ResourceId, 4)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, ResourceId, 8)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, bool, 8)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, float, 16)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, int32_t, 16)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, uint32_t, 16)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, double, 16)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, uint64_t, 16)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, int64_t, 16)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, uint16_t, 16)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, int16_t, 16)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, uint8_t, 16)
TEMPLATE_FIXEDARRAY_INSTANTIATE(rdcfixedarray, int8_t, 16)
// list of array types. These are the concrete types used in rdcarray that will be bound
// If you get an error with add_your_use_of_rdcarray_to_swig_interface missing, add your type here
// or in qrenderdoc.i, depending on which one is appropriate