+ if (!PyObject_IsSubclass(d->py_dec, py_basedec)) {
+ srd_err("Decoder class in protocol decoder module %s is not "
+ "a subclass of sigrokdecode.Decoder.", module_name);
+ goto err_out;
+ }
+ Py_CLEAR(py_basedec);
+
+ /* Check for a proper start() method. */
+ if (!PyObject_HasAttrString(d->py_dec, "start")) {
+ srd_err("Protocol decoder %s has no start() method Decoder "
+ "class.", module_name);
+ goto err_out;
+ }
+ py_method = PyObject_GetAttrString(d->py_dec, "start");
+ if (!PyFunction_Check(py_method)) {
+ srd_err("Protocol decoder %s Decoder class attribute 'start' "
+ "is not a method.", module_name);
+ goto err_out;
+ }
+ Py_CLEAR(py_method);
+
+ /* Check for a proper decode() method. */
+ if (!PyObject_HasAttrString(d->py_dec, "decode")) {
+ srd_err("Protocol decoder %s has no decode() method Decoder "
+ "class.", module_name);
+ goto err_out;
+ }
+ py_method = PyObject_GetAttrString(d->py_dec, "decode");
+ if (!PyFunction_Check(py_method)) {
+ srd_err("Protocol decoder %s Decoder class attribute 'decode' "
+ "is not a method.", module_name);
+ goto err_out;
+ }
+ Py_CLEAR(py_method);
+
+ /* If present, options must be a dictionary. */
+ if (PyObject_HasAttrString(d->py_dec, "options")) {
+ py_attr = PyObject_GetAttrString(d->py_dec, "options");
+ if (!PyDict_Check(py_attr)) {
+ srd_err("Protocol decoder %s options attribute is not "
+ "a dictionary.", d->name);
+ Py_DecRef(py_attr);
+ goto err_out;
+ }
+ Py_DecRef(py_attr);
+ }