halmodule: factor out to/from python functions
.. which will be used by the stream code too. Signed-off-by: Jeff Epler <jepler@unpythonic.net>
This commit is contained in:
parent
eef9f52585
commit
2b6c8ad710
1 changed files with 133 additions and 91 deletions
|
|
@ -40,6 +40,105 @@ typedef int Py_ssize_t;
|
||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
PyObject *to_python(bool b) {
|
||||||
|
return PyBool_FromLong(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *to_python(unsigned u) {
|
||||||
|
if(u < LONG_MAX) return PyInt_FromLong(u);
|
||||||
|
return PyLong_FromUnsignedLong(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *to_python(int u) {
|
||||||
|
return PyInt_FromLong(u);
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *to_python(double d) {
|
||||||
|
return PyFloat_FromDouble(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool from_python(PyObject *o, double *d) {
|
||||||
|
if(PyFloat_Check(o)) {
|
||||||
|
*d = PyFloat_AsDouble(o);
|
||||||
|
return true;
|
||||||
|
} else if(PyInt_Check(o)) {
|
||||||
|
*d = PyInt_AsLong(o);
|
||||||
|
return true;
|
||||||
|
} else if(PyLong_Check(o)) {
|
||||||
|
*d = PyLong_AsDouble(o);
|
||||||
|
return !PyErr_Occurred();
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject *tmp = PyNumber_Float(o);
|
||||||
|
if(!tmp) {
|
||||||
|
PyErr_Format(PyExc_TypeError, "Number expected, not %s",
|
||||||
|
o->ob_type->tp_name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*d = PyFloat_AsDouble(tmp);
|
||||||
|
Py_DECREF(tmp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool from_python(PyObject *o, uint32_t *u) {
|
||||||
|
PyObject *tmp = 0;
|
||||||
|
long long l;
|
||||||
|
if(PyInt_Check(o)) {
|
||||||
|
l = PyInt_AsLong(o);
|
||||||
|
goto got_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = PyLong_Check(o) ? o : PyNumber_Long(tmp);
|
||||||
|
if(!tmp) goto fail;
|
||||||
|
|
||||||
|
int overflow;
|
||||||
|
l = PyLong_AsLongLongAndOverflow(tmp, &overflow);
|
||||||
|
if(overflow) goto fail;
|
||||||
|
|
||||||
|
got_value:
|
||||||
|
if(l < 0 || l != (uint32_t)l) {
|
||||||
|
PyErr_Format(PyExc_OverflowError, "Value %lld out of range", l);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
*u = l;
|
||||||
|
if(tmp != o) Py_XDECREF(tmp);
|
||||||
|
return true;
|
||||||
|
fail:
|
||||||
|
if(tmp != o) Py_XDECREF(tmp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool from_python(PyObject *o, int32_t *i) {
|
||||||
|
PyObject *tmp = 0;
|
||||||
|
long long l;
|
||||||
|
if(PyInt_Check(o)) {
|
||||||
|
l = PyInt_AsLong(o);
|
||||||
|
goto got_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = PyLong_Check(o) ? o : PyNumber_Long(tmp);
|
||||||
|
if(!tmp) goto fail;
|
||||||
|
|
||||||
|
int overflow;
|
||||||
|
l = PyLong_AsLongLongAndOverflow(tmp, &overflow);
|
||||||
|
if(overflow) goto fail;
|
||||||
|
|
||||||
|
got_value:
|
||||||
|
if(l != (int32_t)l) {
|
||||||
|
PyErr_Format(PyExc_OverflowError, "Value %lld out of range", l);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
*i = l;
|
||||||
|
if(tmp != o) Py_XDECREF(tmp);
|
||||||
|
return true;
|
||||||
|
fail:
|
||||||
|
if(tmp != o) Py_XDECREF(tmp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
union paramunion {
|
union paramunion {
|
||||||
hal_bit_t b;
|
hal_bit_t b;
|
||||||
hal_u32_t u32;
|
hal_u32_t u32;
|
||||||
|
|
@ -153,8 +252,6 @@ static void pyhal_delete(PyObject *_self) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pyhal_write_common(halitem *pin, PyObject *value) {
|
static int pyhal_write_common(halitem *pin, PyObject *value) {
|
||||||
int is_int = PyInt_Check(value);
|
|
||||||
long intval = is_int ? PyInt_AsLong(value) : -1;
|
|
||||||
if(!pin) return -1;
|
if(!pin) return -1;
|
||||||
|
|
||||||
if(pin->is_pin) {
|
if(pin->is_pin) {
|
||||||
|
|
@ -162,52 +259,24 @@ static int pyhal_write_common(halitem *pin, PyObject *value) {
|
||||||
case HAL_BIT:
|
case HAL_BIT:
|
||||||
*pin->u->pin.b = PyObject_IsTrue(value);
|
*pin->u->pin.b = PyObject_IsTrue(value);
|
||||||
break;
|
break;
|
||||||
case HAL_FLOAT:
|
case HAL_FLOAT: {
|
||||||
if(PyFloat_Check(value))
|
double tmp;
|
||||||
*pin->u->pin.f = PyFloat_AsDouble(value);
|
if(!from_python(value, &tmp)) return -1;
|
||||||
else if(is_int)
|
*pin->u->pin.f = tmp;
|
||||||
*pin->u->pin.f = intval;
|
|
||||||
else if(PyLong_Check(value)) {
|
|
||||||
double fval = PyLong_AsDouble(value);
|
|
||||||
if(PyErr_Occurred()) return -1;
|
|
||||||
*pin->u->pin.f = fval;
|
|
||||||
} else {
|
|
||||||
PyErr_Format(PyExc_TypeError,
|
|
||||||
"Integer or float expected, not %s",
|
|
||||||
value->ob_type->tp_name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case HAL_U32: {
|
case HAL_U32: {
|
||||||
if(is_int) {
|
uint32_t tmp;
|
||||||
if(intval < 0) goto rangeerr;
|
if(!from_python(value, &tmp)) return -1;
|
||||||
if(intval != (rtapi_s32)intval) goto rangeerr;
|
*pin->u->pin.u32 = tmp;
|
||||||
*pin->u->pin.u32 = intval;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!PyLong_Check(value)) {
|
case HAL_S32: {
|
||||||
PyErr_Format(PyExc_TypeError,
|
int32_t tmp;
|
||||||
"Integer or long expected, not %s",
|
if(!from_python(value, &tmp)) return -1;
|
||||||
value->ob_type->tp_name);
|
*pin->u->pin.s32 = tmp;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
unsigned long uintval = PyLong_AsUnsignedLong(value);
|
|
||||||
if(uintval != (rtapi_u32)uintval) goto rangeerr;
|
|
||||||
if(PyErr_Occurred()) return -1;
|
|
||||||
*pin->u->pin.u32 = uintval;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HAL_S32:
|
|
||||||
if(is_int) {
|
|
||||||
if(intval != (rtapi_s32)intval) goto rangeerr;
|
|
||||||
*pin->u->pin.s32 = intval;
|
|
||||||
} else if(PyLong_Check(value)) {
|
|
||||||
intval = PyLong_AsLong(value);
|
|
||||||
if(PyErr_Occurred()) return -1;
|
|
||||||
if(intval != (rtapi_s32)intval) goto rangeerr;
|
|
||||||
*pin->u->pin.u32 = intval;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
PyErr_Format(pyhal_error_type, "Invalid pin type %d", pin->type);
|
PyErr_Format(pyhal_error_type, "Invalid pin type %d", pin->type);
|
||||||
}
|
}
|
||||||
|
|
@ -216,73 +285,46 @@ static int pyhal_write_common(halitem *pin, PyObject *value) {
|
||||||
case HAL_BIT:
|
case HAL_BIT:
|
||||||
pin->u->param.b = PyObject_IsTrue(value);
|
pin->u->param.b = PyObject_IsTrue(value);
|
||||||
break;
|
break;
|
||||||
case HAL_FLOAT:
|
case HAL_FLOAT: {
|
||||||
if(PyFloat_Check(value))
|
int32_t tmp;
|
||||||
pin->u->param.f = PyFloat_AsDouble(value);
|
if(!from_python(value, &tmp)) return -1;
|
||||||
else if(is_int)
|
pin->u->param.f = tmp;
|
||||||
pin->u->param.f = intval;
|
|
||||||
else {
|
|
||||||
PyErr_Format(PyExc_TypeError,
|
|
||||||
"Integer or float expected, not %s",
|
|
||||||
value->ob_type->tp_name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case HAL_U32: {
|
case HAL_U32: {
|
||||||
unsigned long uintval;
|
uint32_t tmp;
|
||||||
if(is_int) {
|
if(!from_python(value, &tmp)) return -1;
|
||||||
if(intval < 0) goto rangeerr;
|
pin->u->param.u32 = tmp;
|
||||||
if(intval != (rtapi_s32)intval) goto rangeerr;
|
|
||||||
pin->u->param.u32 = intval;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!PyLong_Check(value)) {
|
|
||||||
PyErr_Format(PyExc_TypeError,
|
|
||||||
"Integer or long expected, not %s",
|
|
||||||
value->ob_type->tp_name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
uintval = PyLong_AsUnsignedLong(value);
|
|
||||||
if(PyErr_Occurred()) return -1;
|
|
||||||
if(uintval != (rtapi_u32)uintval) goto rangeerr;
|
|
||||||
pin->u->param.u32 = uintval;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case HAL_S32:
|
case HAL_S32:
|
||||||
if(!is_int) goto typeerr;
|
int32_t tmp;
|
||||||
if(intval != (rtapi_s32)intval) goto rangeerr;
|
if(!from_python(value, &tmp)) return -1;
|
||||||
pin->u->param.s32 = intval;
|
pin->u->param.s32 = tmp;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PyErr_Format(pyhal_error_type, "Invalid pin type %d", pin->type);
|
PyErr_Format(pyhal_error_type, "Invalid pin type %d", pin->type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
typeerr:
|
|
||||||
PyErr_Format(PyExc_TypeError, "Integer expected, not %s",
|
|
||||||
value->ob_type->tp_name);
|
|
||||||
return -1;
|
|
||||||
rangeerr:
|
|
||||||
PyErr_Format(PyExc_OverflowError, "Value %ld out of range for pin", intval);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *pyhal_read_common(halitem *item) {
|
static PyObject *pyhal_read_common(halitem *item) {
|
||||||
if(!item) return NULL;
|
if(!item) return NULL;
|
||||||
if(item->is_pin) {
|
if(item->is_pin) {
|
||||||
switch(item->type) {
|
switch(item->type) {
|
||||||
case HAL_BIT: return PyBool_FromLong(*(item->u->pin.b));
|
case HAL_BIT: return to_python(*(item->u->pin.b));
|
||||||
case HAL_U32: return PyLong_FromUnsignedLong(*(item->u->pin.u32));
|
case HAL_U32: return to_python(*(item->u->pin.u32));
|
||||||
case HAL_S32: return PyInt_FromLong(*(item->u->pin.s32));
|
case HAL_S32: return to_python(*(item->u->pin.s32));
|
||||||
case HAL_FLOAT: return PyFloat_FromDouble(*(item->u->pin.f));
|
case HAL_FLOAT: return to_python(*(item->u->pin.f));
|
||||||
case HAL_TYPE_UNSPECIFIED: /* fallthrough */ ;
|
case HAL_TYPE_UNSPECIFIED: /* fallthrough */ ;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch(item->type) {
|
switch(item->type) {
|
||||||
case HAL_BIT: return PyBool_FromLong(item->u->param.b);
|
case HAL_BIT: return to_python(item->u->param.b);
|
||||||
case HAL_U32: return PyLong_FromUnsignedLong(item->u->param.u32);
|
case HAL_U32: return to_python(item->u->param.u32);
|
||||||
case HAL_S32: return PyInt_FromLong(item->u->param.s32);
|
case HAL_S32: return to_python(item->u->param.s32);
|
||||||
case HAL_FLOAT: return PyFloat_FromDouble(item->u->param.f);
|
case HAL_FLOAT: return to_python(item->u->param.f);
|
||||||
case HAL_TYPE_UNSPECIFIED: /* fallthrough */ ;
|
case HAL_TYPE_UNSPECIFIED: /* fallthrough */ ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue