mirror of https://github.com/swig/swig
279 lines
7.0 KiB
OpenEdge ABL
279 lines
7.0 KiB
OpenEdge ABL
// Test customizing slots when using the -builtin option
|
|
|
|
%module python_builtin
|
|
|
|
// throw is invalid in C++17 and later, only SWIG to use it
|
|
#define TESTCASE_THROW1(T1) throw(T1)
|
|
#define TESTCASE_THROW2(T1, T2) throw(T1, T2)
|
|
%{
|
|
#define TESTCASE_THROW1(T1)
|
|
#define TESTCASE_THROW2(T1, T2)
|
|
%}
|
|
|
|
%inline %{
|
|
#ifdef SWIGPYTHON_BUILTIN
|
|
bool is_python_builtin() { return true; }
|
|
#else
|
|
bool is_python_builtin() { return false; }
|
|
#endif
|
|
%}
|
|
|
|
// Test 0 for default tp_hash
|
|
%inline %{
|
|
struct ValueStruct {
|
|
int value;
|
|
ValueStruct(int value) : value(value) {}
|
|
static ValueStruct *inout(ValueStruct *v) {
|
|
return v;
|
|
}
|
|
};
|
|
%}
|
|
|
|
// Test 1a for tp_hash
|
|
#if defined(SWIGPYTHON_BUILTIN)
|
|
%feature("python:tp_hash") SimpleValue "SimpleValueHashFunction"
|
|
#endif
|
|
|
|
%inline %{
|
|
struct SimpleValue {
|
|
int value;
|
|
SimpleValue(int value) : value(value) {}
|
|
};
|
|
%}
|
|
|
|
%{
|
|
#if PY_VERSION_HEX >= 0x03020000
|
|
Py_hash_t SimpleValueHashFunction(PyObject *v)
|
|
#else
|
|
long SimpleValueHashFunction(PyObject *v)
|
|
#endif
|
|
{
|
|
SwigPyObject *sobj = (SwigPyObject *) v;
|
|
SimpleValue *p = (SimpleValue *)sobj->ptr;
|
|
return p->value;
|
|
}
|
|
hashfunc test_hashfunc_cast() {
|
|
return SimpleValueHashFunction;
|
|
}
|
|
%}
|
|
|
|
// Test 1b for tp_hash
|
|
#if defined(SWIGPYTHON_BUILTIN)
|
|
%feature("python:slot", "tp_hash", functype="hashfunc") SimpleValue2::HashFunc;
|
|
#endif
|
|
|
|
%inline %{
|
|
struct SimpleValue2 {
|
|
int value;
|
|
SimpleValue2(int value) : value(value) {}
|
|
#if PY_VERSION_HEX >= 0x03020000
|
|
typedef Py_hash_t HashType;
|
|
#else
|
|
typedef long HashType;
|
|
#endif
|
|
HashType HashFunc() { return (HashType)value; }
|
|
};
|
|
%}
|
|
|
|
// Test 2 for tp_hash
|
|
#if defined(SWIGPYTHON_BUILTIN)
|
|
%feature("python:slot", "tp_hash", functype="hashfunc") BadHashFunctionReturnType::bad_hash_function;
|
|
#endif
|
|
|
|
%inline %{
|
|
struct BadHashFunctionReturnType {
|
|
static const char * bad_hash_function() {
|
|
return "bad hash function";
|
|
}
|
|
};
|
|
%}
|
|
|
|
// Test 3 for tp_hash
|
|
#if defined(SWIGPYTHON_BUILTIN)
|
|
%feature("python:slot", "tp_hash", functype="hashfunc") ExceptionHashFunction::exception_hash_function;
|
|
#endif
|
|
|
|
%catches(const char *) exception_hash_function;
|
|
|
|
%inline %{
|
|
#if PY_VERSION_HEX < 0x03020000
|
|
#define Py_hash_t long
|
|
#endif
|
|
struct ExceptionHashFunction {
|
|
static Py_hash_t exception_hash_function() {
|
|
throw "oops";
|
|
}
|
|
};
|
|
%}
|
|
|
|
// Test 4 for tp_dealloc (which is handled differently to other slots in the SWIG source)
|
|
#if defined(SWIGPYTHON_BUILTIN)
|
|
%feature("python:tp_dealloc") Dealloc1 "Dealloc1Destroyer"
|
|
%feature("python:tp_dealloc") Dealloc2 "Dealloc2Destroyer"
|
|
%feature("python:slot", "tp_dealloc", functype="destructor") Dealloc3::Destroyer;
|
|
#endif
|
|
|
|
%inline %{
|
|
static int Dealloc1CalledCount = 0;
|
|
static int Dealloc2CalledCount = 0;
|
|
static int Dealloc3CalledCount = 0;
|
|
|
|
struct Dealloc1 {
|
|
};
|
|
struct Dealloc2 {
|
|
~Dealloc2() {}
|
|
};
|
|
struct Dealloc3 {
|
|
void Destroyer() {
|
|
Dealloc3CalledCount++;
|
|
delete this;
|
|
}
|
|
};
|
|
%}
|
|
|
|
%{
|
|
void Dealloc1Destroyer(PyObject *v) {
|
|
SwigPyObject *sobj = (SwigPyObject *) v;
|
|
Dealloc1 *p = (Dealloc1 *)sobj->ptr;
|
|
delete p;
|
|
Dealloc1CalledCount++;
|
|
}
|
|
void Dealloc2Destroyer(PyObject *v) {
|
|
SwigPyObject *sobj = (SwigPyObject *) v;
|
|
Dealloc2 *p = (Dealloc2 *)sobj->ptr;
|
|
delete p;
|
|
Dealloc2CalledCount++;
|
|
}
|
|
%}
|
|
|
|
// Test 5 for python:compare feature
|
|
%feature("python:compare", "Py_LT") MyClass::lessThan;
|
|
|
|
%inline %{
|
|
class MyClass {
|
|
public:
|
|
MyClass(int val = 0) : val(val) {}
|
|
bool lessThan(const MyClass& other) const {
|
|
less_than_counts++;
|
|
return val < other.val;
|
|
}
|
|
int val;
|
|
static int less_than_counts;
|
|
};
|
|
int MyClass::less_than_counts = 0;
|
|
%}
|
|
|
|
// Test 6 add in container __getitem__ to support basic sequence protocol
|
|
// Tests overloaded functions being used for more than one slot (mp_subscript and sq_item)
|
|
%include <exception.i>
|
|
%include <std_except.i>
|
|
%apply int {Py_ssize_t}
|
|
%typemap(in) PySliceObject * {
|
|
if (!PySlice_Check($input))
|
|
SWIG_exception(SWIG_TypeError, "in method '$symname', argument $argnum of type '$type'");
|
|
$1 = (PySliceObject *)$input;
|
|
}
|
|
%typemap(typecheck,precedence=300) PySliceObject* {
|
|
$1 = PySlice_Check($input);
|
|
}
|
|
|
|
%feature("python:slot", "mp_subscript", functype="binaryfunc") SimpleArray::__getitem__(PySliceObject *slice);
|
|
%feature("python:slot", "sq_item", functype="ssizeargfunc") SimpleArray::__getitem__(Py_ssize_t n);
|
|
%feature("python:slot", "sq_length", functype="lenfunc") SimpleArray::__len__;
|
|
%inline %{
|
|
class SimpleArray {
|
|
Py_ssize_t size;
|
|
int numbers[5];
|
|
public:
|
|
SimpleArray(Py_ssize_t size) : size(size) {
|
|
for (Py_ssize_t x = 0; x<size; ++x)
|
|
numbers[x] = (int)x*10;
|
|
}
|
|
|
|
Py_ssize_t __len__() {
|
|
return size;
|
|
}
|
|
|
|
int __getitem__(Py_ssize_t n) TESTCASE_THROW1(std::out_of_range) {
|
|
if (n >= (int)size)
|
|
throw std::out_of_range("Index too large");
|
|
return numbers[n];
|
|
}
|
|
|
|
SimpleArray __getitem__(PySliceObject *slice) TESTCASE_THROW2(std::out_of_range, std::invalid_argument) {
|
|
if (!PySlice_Check(slice))
|
|
throw std::invalid_argument("Slice object expected");
|
|
Py_ssize_t i, j, step;
|
|
#if PY_VERSION_HEX >= 0x03020000
|
|
PySlice_GetIndices((PyObject *)slice, size, &i, &j, &step);
|
|
#else
|
|
PySlice_GetIndices((PySliceObject *)slice, size, &i, &j, &step);
|
|
#endif
|
|
if (step != 1)
|
|
throw std::invalid_argument("Only a step size of 1 is implemented");
|
|
|
|
{
|
|
Py_ssize_t ii = i<0 ? 0 : i>=size ? size-1 : i;
|
|
Py_ssize_t jj = j<0 ? 0 : j>=size ? size-1 : j;
|
|
if (ii > jj)
|
|
throw std::invalid_argument("getitem i should not be larger than j");
|
|
SimpleArray n(jj-ii);
|
|
for (Py_ssize_t x = 0; x<size; ++x)
|
|
n.numbers[x] = numbers[x+ii];
|
|
return n;
|
|
}
|
|
}
|
|
};
|
|
%}
|
|
|
|
// Test 7 mapping to Python's pow
|
|
%pybinoperator(__pow__, ANumber::power, ternaryfunc, nb_power);
|
|
|
|
%inline %{
|
|
class ANumber {
|
|
int num;
|
|
public:
|
|
ANumber(int d = 0) : num(d) {}
|
|
ANumber __pow__(const ANumber &other, const ANumber *x = 0) const {
|
|
int val = (int)pow(num, other.num);
|
|
val = x ? val % x->num : val;
|
|
return ANumber(val);
|
|
}
|
|
int Value() const {
|
|
return num;
|
|
}
|
|
};
|
|
%}
|
|
|
|
// Test 8 https://github.com/swig/swig/pull/2771 __setitem__ for deleting item, uses C NULL
|
|
%feature("python:slot", "sq_item", functype="ssizeargfunc") GetSetItem::__getitem__;
|
|
%feature("python:slot", "sq_ass_item", functype="ssizeobjargproc") GetSetItem::__setitem__;
|
|
%feature("python:slot", "tp_call", functype="ternaryfunc") GetSetItem::__call__;
|
|
%typemap(default) PyObject* value {$1 = NULL;}
|
|
|
|
%inline %{
|
|
class GetSetItem {
|
|
public:
|
|
int idx, value, args_count, kw_count;
|
|
GetSetItem() : idx(), value(), args_count(), kw_count() { reset(); }
|
|
int __getitem__(int idx) {
|
|
this->idx = idx;
|
|
return 123;
|
|
}
|
|
void __setitem__(int idx, PyObject* value) {
|
|
this->idx = idx;
|
|
this->value = value ? (int)PyInt_AsLong(value) : -11;
|
|
}
|
|
void __call__(PyObject* args, PyObject* kw) {
|
|
this->args_count = args ? (int)PyTuple_Size(args) : -11;
|
|
this->kw_count = kw ? (int)PyDict_Size(kw) : -11;
|
|
}
|
|
void reset() {
|
|
idx = -100;
|
|
value = -100;
|
|
args_count = -100;
|
|
kw_count = -100;
|
|
}
|
|
};
|
|
%}
|