Add Babeltrace 2 Python bindings
[babeltrace.git] / bindings / python / bt2 / native_btcomponentclass.i
1 /*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25 %{
26 #include <babeltrace/component/component-class.h>
27 #include <babeltrace/component/component-class-source.h>
28 #include <babeltrace/component/component-class-sink.h>
29 #include <babeltrace/component/component-class-filter.h>
30 #include <babeltrace/component/notification/iterator.h>
31 #include <babeltrace/component/notification/notification.h>
32 #include <assert.h>
33 #include <glib.h>
34 %}
35
36 /* Types */
37 struct bt_component_class;
38
39 /* Status */
40 enum bt_component_class_type {
41 BT_COMPONENT_CLASS_TYPE_UNKNOWN = -1,
42 BT_COMPONENT_CLASS_TYPE_SOURCE = 0,
43 BT_COMPONENT_CLASS_TYPE_SINK = 1,
44 BT_COMPONENT_CLASS_TYPE_FILTER = 2,
45 };
46
47 /* General functions */
48 const char *bt_component_class_get_name(
49 struct bt_component_class *component_class);
50 const char *bt_component_class_get_description(
51 struct bt_component_class *component_class);
52 enum bt_component_class_type bt_component_class_get_type(
53 struct bt_component_class *component_class);
54
55 %{
56 /*
57 * This hash table associates a BT component class object address to a
58 * user-defined Python class (PyObject *). The keys and values are NOT
59 * owned by this hash table. The Python class objects are owned by the
60 * Python module, which should not be unloaded until it is not possible
61 * to create a user Python component anyway.
62 *
63 * This hash table is written to when a user-defined Python component
64 * class is created by one of the bt_py3_component_class_*_create()
65 * functions.
66 *
67 * This function is read from when a user calls bt_component_create()
68 * with a component class pointer created by one of the functions above.
69 * In this case, the original Python class needs to be found to
70 * instantiate it and associate the created Python component object with
71 * a BT component object instance.
72 */
73
74 static GHashTable *bt_cc_ptr_to_py_cls;
75
76 static void register_cc_ptr_to_py_cls(struct bt_component_class *bt_cc,
77 PyObject *py_cls)
78 {
79 g_hash_table_insert(bt_cc_ptr_to_py_cls, (gpointer) bt_cc,
80 (gpointer) py_cls);
81 }
82
83 static PyObject *lookup_cc_ptr_to_py_cls(struct bt_component_class *bt_cc)
84 {
85 return (PyObject *) g_hash_table_lookup(bt_cc_ptr_to_py_cls,
86 (gconstpointer) bt_cc);
87 }
88
89
90 /*
91 * Useful Python objects.
92 */
93
94 static PyObject *py_mod_bt2 = NULL;
95 static PyObject *py_mod_bt2_exc_error_type = NULL;
96 static PyObject *py_mod_bt2_exc_unsupported_feature_type = NULL;
97 static PyObject *py_mod_bt2_exc_try_again_type = NULL;
98 static PyObject *py_mod_bt2_exc_stop_type = NULL;
99 static PyObject *py_mod_bt2_values = NULL;
100 static PyObject *py_mod_bt2_values_create_from_ptr_func = NULL;
101
102 static void bt_py3_cc_init_from_bt2(void)
103 {
104 /*
105 * This is called once the bt2 package is loaded.
106 *
107 * Those modules and functions are needed while the package is
108 * used. Loading them here is safe because we know the bt2
109 * package is imported, and we know that the user cannot use the
110 * code here without importing bt2 first.
111 */
112 py_mod_bt2 = PyImport_ImportModule("bt2");
113 assert(py_mod_bt2);
114 py_mod_bt2_values = PyImport_ImportModule("bt2.values");
115 assert(py_mod_bt2_values);
116 py_mod_bt2_values_create_from_ptr_func =
117 PyObject_GetAttrString(py_mod_bt2_values,
118 "_create_from_ptr");
119 assert(py_mod_bt2_values_create_from_ptr_func);
120 py_mod_bt2_exc_error_type =
121 PyObject_GetAttrString(py_mod_bt2, "Error");
122 assert(py_mod_bt2_exc_error_type);
123 py_mod_bt2_exc_unsupported_feature_type =
124 PyObject_GetAttrString(py_mod_bt2, "UnsupportedFeature");
125 py_mod_bt2_exc_try_again_type =
126 PyObject_GetAttrString(py_mod_bt2, "TryAgain");
127 py_mod_bt2_exc_stop_type =
128 PyObject_GetAttrString(py_mod_bt2, "Stop");
129 assert(py_mod_bt2_exc_stop_type);
130 }
131
132 static void bt_py3_cc_exit_handler(void)
133 {
134 /*
135 * This is an exit handler (set by the bt2 package).
136 *
137 * We only give back the references that we took in
138 * bt_py3_cc_init_from_bt2() here. The global variables continue
139 * to exist for the code of this file, but they are now borrowed
140 * references. If this code is executed, it means that somehow
141 * to modules are still loaded, so it should be safe to use them
142 * even without a strong reference.
143 *
144 * We cannot do this in the library's destructor because it
145 * gets executed once Python is already finalized.
146 */
147 Py_XDECREF(py_mod_bt2_values_create_from_ptr_func);
148 Py_XDECREF(py_mod_bt2_values);
149 Py_XDECREF(py_mod_bt2);
150 Py_XDECREF(py_mod_bt2_exc_error_type);
151 Py_XDECREF(py_mod_bt2_exc_unsupported_feature_type);
152 Py_XDECREF(py_mod_bt2_exc_try_again_type);
153 Py_XDECREF(py_mod_bt2_exc_stop_type);
154 }
155
156
157 /* Library constructor and destructor */
158
159 __attribute__((constructor))
160 static void bt_py3_native_comp_class_ctor(void) {
161 /* Initialize component class association hash table */
162 bt_cc_ptr_to_py_cls = g_hash_table_new(g_direct_hash, g_direct_equal);
163 assert(bt_cc_ptr_to_py_cls);
164 }
165
166 __attribute__((destructor))
167 static void bt_py3_native_comp_class_dtor(void) {
168 /* Destroy component class association hash table */
169 if (bt_cc_ptr_to_py_cls) {
170 g_hash_table_destroy(bt_cc_ptr_to_py_cls);
171 }
172 }
173
174
175 /* Converts a BT value object to a bt2.values object */
176
177 static PyObject *bt_py3_bt_value_from_ptr(struct bt_value *value)
178 {
179 PyObject *py_create_from_ptr_func = NULL;
180 PyObject *py_value = NULL;
181 PyObject *py_ptr = NULL;
182
183 py_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(value),
184 SWIGTYPE_p_bt_value, 0);
185 py_value = PyObject_CallFunctionObjArgs(
186 py_mod_bt2_values_create_from_ptr_func, py_ptr, NULL);
187 if (!py_value) {
188 goto end;
189 }
190
191 /*
192 * _create_from_ptr() only wraps an existing reference. `value`
193 * is a borrowed reference here, so increment its reference
194 * count for this new owner.
195 */
196 bt_get(value);
197
198 end:
199 Py_XDECREF(py_ptr);
200 PyErr_Clear();
201 return py_value;
202 }
203
204
205 /* self.__init__(*args, **kwargs) */
206
207 static int bt_py3_call_self_init(PyObject *py_self, PyObject *py_args,
208 PyObject *py_kwargs)
209 {
210 int ret = 0;
211 size_t i;
212 PyObject *py_init_method_result = NULL;
213 PyObject *py_init_method = NULL;
214 PyObject *py_init_method_args = NULL;
215 PyObject *py_class = NULL;
216
217 py_class = PyObject_GetAttrString(py_self, "__class__");
218 if (!py_class) {
219 goto error;
220 }
221
222 py_init_method = PyObject_GetAttrString(py_class, "__init__");
223 if (!py_init_method) {
224 goto error;
225 }
226
227 /* Prepend py_self to the arguments (copy them to new tuple) */
228 py_init_method_args = PyTuple_New(PyTuple_Size(py_args) + 1);
229 if (!py_init_method_args) {
230 goto error;
231 }
232
233 Py_INCREF(py_self);
234 ret = PyTuple_SetItem(py_init_method_args, 0, py_self);
235 if (ret < 0) {
236 Py_DECREF(py_self);
237 goto error;
238 }
239
240 for (i = 0; i < PyTuple_Size(py_args); i++) {
241 PyObject *obj = PyTuple_GetItem(py_args, i);
242 if (!obj) {
243 goto error;
244 }
245
246 Py_INCREF(obj);
247 ret = PyTuple_SetItem(py_init_method_args, i + 1, obj);
248 if (ret < 0) {
249 Py_DECREF(obj);
250 goto error;
251 }
252 }
253
254 py_init_method_result = PyObject_Call(py_init_method,
255 py_init_method_args, py_kwargs);
256 if (!py_init_method_result) {
257 goto error;
258 }
259
260 goto end;
261
262 error:
263 ret = -1;
264
265 end:
266 Py_XDECREF(py_init_method_args);
267 Py_XDECREF(py_init_method_result);
268 Py_XDECREF(py_init_method);
269 Py_XDECREF(py_class);
270 return ret;
271 }
272
273
274 /* Component class proxy methods (delegate to the attached Python object) */
275
276 static enum bt_component_status bt_py3_cc_init(
277 struct bt_component *component, struct bt_value *params,
278 void *init_method_data)
279 {
280 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
281 int ret;
282
283 /*
284 * This function is either called from
285 * _UserComponentType.__call__() (when init_method_data contains
286 * the PyObject * currently creating this component) or from
287 * other code (init_method_data is NULL).
288 */
289 if (init_method_data) {
290 /*
291 * Called from _UserComponentType.__call__().
292 *
293 * The `params` argument is completely ignored here,
294 * because if the user creating the component object
295 * from the component class object wants parameters,
296 * they'll be in the keyword arguments anyway.
297 */
298 PyObject *py_comp = init_method_data;
299 PyObject *py_comp_ptr = NULL;
300 PyObject *py_init_args = NULL;
301 PyObject *py_init_kwargs = NULL;
302
303 /*
304 * No need to take a Python reference on py_comp here:
305 * we store it as a _borrowed_ reference. When all the
306 * Python references are dropped, the object's __del__()
307 * method is called. This method calls this side
308 * (bt_py3_component_on_del()) to swap the ownership:
309 * this BT component becomes the only owner of the
310 * Python object.
311 */
312 bt_component_set_private_data(component, py_comp);
313
314 /*
315 * Set this BT component pointer as py_comp._ptr, and
316 * take a reference on it (on success, at the end).
317 *
318 * This reference is put in the Python component
319 * object's __del__() method.
320 */
321 py_comp_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(component),
322 SWIGTYPE_p_bt_component, 0);
323 if (!py_comp_ptr) {
324 PyErr_Clear();
325 goto with_init_method_data_error;
326 }
327
328 ret = PyObject_SetAttrString(py_comp, "_ptr", py_comp_ptr);
329 if (ret < 0) {
330 PyErr_Clear();
331 goto with_init_method_data_error;
332 }
333
334 /*
335 * _UserComponentType.__call__() puts the arguments and
336 * keyword arguments to use for the py_comp.__init__()
337 * call in py_comp._init_args and py_comp._init_kwargs.
338 *
339 * We need to get them and remove them from py_comp before
340 * calling py_comp.__init__().
341 */
342 py_init_args = PyObject_GetAttrString(py_comp, "_init_args");
343 if (!py_init_args) {
344 PyErr_Clear();
345 goto with_init_method_data_error;
346 }
347
348 py_init_kwargs = PyObject_GetAttrString(py_comp, "_init_kwargs");
349 if (!py_init_kwargs) {
350 PyErr_Clear();
351 goto with_init_method_data_error;
352 }
353
354 ret = PyObject_DelAttrString(py_comp, "_init_args");
355 if (ret < 0) {
356 PyErr_Clear();
357 goto with_init_method_data_error;
358 }
359
360 ret = PyObject_DelAttrString(py_comp, "_init_kwargs");
361 if (ret < 0) {
362 PyErr_Clear();
363 goto with_init_method_data_error;
364 }
365
366 /* Ready to call py_comp.__init__() */
367 ret = bt_py3_call_self_init(py_comp, py_init_args,
368 py_init_kwargs);
369 if (ret) {
370 /*
371 * We do not clear any raised exception here
372 * so that the Python caller (the one who is
373 * instantiating the class) gets the exception
374 * from the __init__() method.
375 */
376 goto with_init_method_data_error;
377 }
378
379 /*
380 * py_comp.__init__() went well: get the native BT
381 * component object reference for the Python object.
382 */
383 bt_get(component);
384 goto with_init_method_data_end;
385
386 with_init_method_data_error:
387 status = BT_COMPONENT_STATUS_ERROR;
388
389 /*
390 * Reset py_comp._ptr to None to signal the error to
391 * _UserComponentType.__call__(). For exceptions raised
392 * from py_comp.__init__(), this is not important,
393 * because __call__() will also raise before even
394 * checking py_comp._ptr.
395 */
396 if (PyObject_HasAttrString(py_comp, "_ptr")) {
397 PyObject *py_err_type, *py_err_value, *py_err_traceback;
398 PyErr_Fetch(&py_err_type, &py_err_value,
399 &py_err_traceback);
400 Py_INCREF(Py_None);
401 PyObject_SetAttrString(py_comp, "_ptr", Py_None);
402 PyErr_Restore(py_err_type, py_err_value,
403 py_err_traceback);
404 }
405
406 /*
407 * Important: remove py_comp from our the BT component's
408 * private data. Since we're failing,
409 * bt_py3_cc_destroy() is about to be called: it must
410 * not consider py_comp. py_comp's __del__() method
411 * will be called (because the instance exists), but
412 * since py_comp._ptr is None, it won't do anything.
413 */
414 bt_component_set_private_data(component, NULL);
415
416 with_init_method_data_end:
417 Py_XDECREF(py_comp_ptr);
418 Py_XDECREF(py_init_args);
419 Py_XDECREF(py_init_kwargs);
420 } else {
421 /*
422 * Not called from _UserComponentType.__call__().
423 *
424 * In this case we need to instantiate the user-defined
425 * Python class. To do this we call the user-defined
426 * class manually with this already-created BT component
427 * object pointer as the __comp_ptr keyword argument.
428 *
429 * We keep a reference, the only existing one, to the
430 * created Python object. bt_py3_component_on_del() will
431 * never be called by the object's __del__() method
432 * because _UserComponentType.__call__() marks the
433 * object as owned by the native BT component object.
434 */
435 PyObject *py_cls = NULL;
436 PyObject *py_comp = NULL;
437 PyObject *py_params = NULL;
438 PyObject *py_comp_ptr = NULL;
439 PyObject *py_cls_ctor_args = NULL;
440 PyObject *py_cls_ctor_kwargs = NULL;
441
442 /*
443 * Get the user-defined Python class which created this
444 * component's class in the first place (borrowed
445 * reference).
446 */
447 py_cls = lookup_cc_ptr_to_py_cls(bt_component_get_class(component));
448 if (!py_cls) {
449 goto without_init_method_data_error;
450 }
451
452 /* BT value object -> Python bt2.values object */
453 py_params = bt_py3_bt_value_from_ptr(params);
454 if (!py_params) {
455 goto without_init_method_data_error;
456 }
457
458 /* Component pointer -> SWIG pointer Python object */
459 py_comp_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(component),
460 SWIGTYPE_p_bt_component, 0);
461 if (!py_comp_ptr) {
462 goto without_init_method_data_error;
463 }
464
465 /*
466 * Do the equivalent of this:
467 *
468 * py_comp = py_cls(__comp_ptr=py_comp_ptr, params=py_params)
469 *
470 * _UserComponentType.__call__() calls the Python
471 * component object's __init__() function itself in this
472 * case.
473 */
474 py_cls_ctor_args = PyTuple_New(0);
475 if (!py_cls_ctor_args) {
476 goto without_init_method_data_error;
477 }
478
479 py_cls_ctor_kwargs = PyDict_New();
480 if (!py_cls_ctor_kwargs) {
481 goto without_init_method_data_error;
482 }
483
484 ret = PyDict_SetItemString(py_cls_ctor_kwargs, "__comp_ptr",
485 py_comp_ptr);
486 if (ret < 0) {
487 goto without_init_method_data_error;
488 }
489
490 ret = PyDict_SetItemString(py_cls_ctor_kwargs, "params",
491 py_params);
492 if (ret < 0) {
493 goto without_init_method_data_error;
494 }
495
496 py_comp = PyObject_Call(py_cls, py_cls_ctor_args,
497 py_cls_ctor_kwargs);
498 if (!py_comp) {
499 goto without_init_method_data_error;
500 }
501
502 /*
503 * Our user Python component object is now fully created
504 * and initialized by the user. Since we just created
505 * it, this BT component is its only (persistent) owner.
506 */
507 bt_component_set_private_data(component, py_comp);
508 py_comp = NULL;
509 goto without_init_method_data_end;
510
511 without_init_method_data_error:
512 status = BT_COMPONENT_STATUS_ERROR;
513
514 /*
515 * Clear any exception: we're returning a bad status
516 * anyway. If this call originated from Python (creation
517 * from a plugin's component class, for example), then
518 * the user gets an appropriate creation error.
519 */
520 PyErr_Clear();
521
522 without_init_method_data_end:
523 Py_XDECREF(py_comp);
524 Py_XDECREF(py_params);
525 Py_XDECREF(py_comp_ptr);
526 Py_XDECREF(py_cls_ctor_args);
527 Py_XDECREF(py_cls_ctor_kwargs);
528 }
529
530 return status;
531 }
532
533 static void bt_py3_cc_destroy(struct bt_component *component)
534 {
535 PyObject *py_comp = bt_component_get_private_data(component);
536 PyObject *py_destroy_method_result = NULL;
537
538 if (py_comp) {
539 /*
540 * If we're here, this BT component is the only owner of
541 * its private user Python object. It is safe to
542 * decrement its reference count, and thus destroy it.
543 *
544 * We call its _destroy() method before doing so to notify
545 * the Python user.
546 */
547 py_destroy_method_result = PyObject_CallMethod(py_comp,
548 "_destroy", NULL);
549
550 /*
551 * Ignore any exception raised by the _destroy() method
552 * because it won't change anything at this point: the
553 * component is being destroyed anyway.
554 */
555 PyErr_Clear();
556 Py_XDECREF(py_destroy_method_result);
557 Py_DECREF(py_comp);
558 }
559 }
560
561 static enum bt_notification_iterator_status bt_py3_exc_to_notif_iter_status(void)
562 {
563 enum bt_notification_iterator_status status =
564 BT_NOTIFICATION_ITERATOR_STATUS_OK;
565 PyObject *exc = PyErr_Occurred();
566
567 if (!exc) {
568 goto end;
569 }
570
571 if (PyErr_GivenExceptionMatches(exc,
572 py_mod_bt2_exc_unsupported_feature_type)) {
573 status = BT_NOTIFICATION_ITERATOR_STATUS_UNSUPPORTED;
574 } else if (PyErr_GivenExceptionMatches(exc,
575 py_mod_bt2_exc_stop_type)) {
576 status = BT_NOTIFICATION_ITERATOR_STATUS_END;
577 } else {
578 status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
579 }
580
581 end:
582 PyErr_Clear();
583 return status;
584 }
585
586 static enum bt_notification_iterator_status bt_py3_cc_notification_iterator_init(
587 struct bt_component *component,
588 struct bt_notification_iterator *iter, void *init_method_data)
589 {
590 enum bt_notification_iterator_status status =
591 BT_NOTIFICATION_ITERATOR_STATUS_OK;
592 PyObject *py_comp_cls = NULL;
593 PyObject *py_iter_cls = NULL;
594 PyObject *py_iter_ptr = NULL;
595 PyObject *py_init_method_result = NULL;
596 PyObject *py_iter = NULL;
597 PyObject *py_comp = bt_component_get_private_data(component);
598
599 /* Find user's Python notification iterator class */
600 py_comp_cls = PyObject_GetAttrString(py_comp, "__class__");
601 if (!py_comp_cls) {
602 goto error;
603 }
604
605 py_iter_cls = PyObject_GetAttrString(py_comp_cls, "_iter_cls");
606 if (!py_iter_cls) {
607 goto error;
608 }
609
610 /*
611 * Create object with borrowed BT notification iterator
612 * reference:
613 *
614 * py_iter = py_iter_cls.__new__(py_iter_cls, py_iter_ptr)
615 */
616 py_iter_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(iter),
617 SWIGTYPE_p_bt_notification_iterator, 0);
618 if (!py_iter_ptr) {
619 goto error;
620 }
621
622 py_iter = PyObject_CallMethod(py_iter_cls, "__new__",
623 "(OO)", py_iter_cls, py_iter_ptr);
624 if (!py_iter) {
625 goto error;
626 }
627
628 /*
629 * Initialize object:
630 *
631 * py_iter.__init__()
632 *
633 * At this point, py_iter._ptr is set, so this initialization
634 * function has access to the py_iter.component property (which
635 * gives it the user Python component object from which the
636 * iterator was created).
637 */
638 py_init_method_result = PyObject_CallMethod(py_iter, "__init__", NULL);
639 if (!py_init_method_result) {
640 goto error;
641 }
642
643 /*
644 * Since the Python code can never instantiate a user-defined
645 * notification iterator class, the BT notification iterator
646 * object does NOT belong to a user Python notification iterator
647 * object (borrowed reference). However this Python object is
648 * owned by this BT notification iterator object.
649 *
650 * In the Python world, the lifetime of the BT notification
651 * iterator is managed by a _GenericNotificationIterator
652 * instance:
653 *
654 * _GenericNotificationIterator instance:
655 * owns a native bt_notification_iterator object (iter)
656 * owns a UserNotificationIterator instance (py_iter)
657 * self._ptr is a borrowed reference to the
658 * native bt_notification_iterator object (iter)
659 */
660 bt_notification_iterator_set_private_data(iter, py_iter);
661 py_iter = NULL;
662 goto end;
663
664 error:
665 status = bt_py3_exc_to_notif_iter_status();
666 if (status == BT_NOTIFICATION_ITERATOR_STATUS_OK) {
667 /*
668 * Looks like there wasn't any exception from the Python
669 * side, but we're still in an error state here.
670 */
671 status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
672 }
673
674 /*
675 * Clear any exception: we're returning a bad status anyway. If
676 * this call originated from Python, then the user gets an
677 * appropriate creation error.
678 */
679 PyErr_Clear();
680
681 end:
682 Py_XDECREF(py_comp_cls);
683 Py_XDECREF(py_iter_cls);
684 Py_XDECREF(py_iter_ptr);
685 Py_XDECREF(py_init_method_result);
686 Py_XDECREF(py_iter);
687 return status;
688 }
689
690 static void bt_py3_cc_notification_iterator_destroy(
691 struct bt_notification_iterator *iter)
692 {
693 PyObject *py_notif_iter =
694 bt_notification_iterator_get_private_data(iter);
695 PyObject *py_destroy_method_result = NULL;
696
697 assert(py_notif_iter);
698 py_destroy_method_result = PyObject_CallMethod(py_notif_iter,
699 "_destroy", NULL);
700
701 /*
702 * Ignore any exception raised by the _destroy() method because
703 * it won't change anything at this point. The notification
704 * iterator is being destroyed anyway.
705 */
706 PyErr_Clear();
707 Py_XDECREF(py_destroy_method_result);
708 Py_DECREF(py_notif_iter);
709 }
710
711 static struct bt_notification *bt_py3_cc_notification_iterator_get(
712 struct bt_notification_iterator *iter)
713 {
714 PyObject *py_notif_iter =
715 bt_notification_iterator_get_private_data(iter);
716 PyObject *py_get_method_result = NULL;
717 struct bt_notification *notif = NULL;
718
719 assert(py_notif_iter);
720 py_get_method_result = PyObject_CallMethod(py_notif_iter,
721 "_get_from_bt", NULL);
722 if (!py_get_method_result) {
723 goto error;
724 }
725
726 /*
727 * The returned object, on success, is an integer object
728 * (PyLong) containing the address of a BT notification
729 * object (which is not ours).
730 */
731 notif = (struct bt_notification *) PyLong_AsUnsignedLongLong(
732 py_get_method_result);
733
734 /* Clear potential overflow error; should never happen */
735 if (PyErr_Occurred()) {
736 goto error;
737 }
738
739 if (!notif) {
740 goto error;
741 }
742
743 goto end;
744
745 error:
746 BT_PUT(notif);
747
748 /*
749 * Clear any exception: we're returning NULL anyway. If this
750 * call originated from Python, then the user gets an
751 * appropriate error.
752 */
753 PyErr_Clear();
754
755 end:
756 Py_XDECREF(py_get_method_result);
757 return notif;
758 }
759
760 static enum bt_notification_iterator_status bt_py3_cc_notification_iterator_next(
761 struct bt_notification_iterator *iter)
762 {
763 enum bt_notification_iterator_status status;
764 PyObject *py_notif_iter =
765 bt_notification_iterator_get_private_data(iter);
766 PyObject *py_next_method_result = NULL;
767
768 assert(py_notif_iter);
769 py_next_method_result = PyObject_CallMethod(py_notif_iter,
770 "_next", NULL);
771 status = bt_py3_exc_to_notif_iter_status();
772 if (!py_next_method_result
773 && status == BT_NOTIFICATION_ITERATOR_STATUS_OK) {
774 /* Pretty sure this should never happen, but just in case */
775 status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
776 }
777
778 Py_XDECREF(py_next_method_result);
779 return status;
780 }
781
782 static enum bt_notification_iterator_status bt_py3_cc_notification_iterator_seek_time(
783 struct bt_notification_iterator *iter, int64_t time)
784 {
785 enum bt_notification_iterator_status status;
786 PyObject *py_notif_iter =
787 bt_notification_iterator_get_private_data(iter);
788 PyObject *py_seek_to_time_method_result = NULL;
789
790 assert(py_notif_iter);
791 py_seek_to_time_method_result = PyObject_CallMethod(py_notif_iter,
792 "_seek_to_time", "(L)", time);
793 status = bt_py3_exc_to_notif_iter_status();
794 if (!py_seek_to_time_method_result
795 && status == BT_NOTIFICATION_ITERATOR_STATUS_OK) {
796 /* Pretty sure this should never happen, but just in case */
797 status = BT_NOTIFICATION_ITERATOR_STATUS_ERROR;
798 }
799
800 Py_XDECREF(py_seek_to_time_method_result);
801 return status;
802 }
803
804 static enum bt_component_status bt_py3_exc_to_component_status(void)
805 {
806 enum bt_component_status status = BT_COMPONENT_STATUS_OK;
807 PyObject *exc = PyErr_Occurred();
808
809 if (!exc) {
810 goto end;
811 }
812
813 if (PyErr_GivenExceptionMatches(exc,
814 py_mod_bt2_exc_unsupported_feature_type)) {
815 status = BT_COMPONENT_STATUS_UNSUPPORTED;
816 } else if (PyErr_GivenExceptionMatches(exc,
817 py_mod_bt2_exc_try_again_type)) {
818 status = BT_COMPONENT_STATUS_AGAIN;
819 } else if (PyErr_GivenExceptionMatches(exc,
820 py_mod_bt2_exc_stop_type)) {
821 status = BT_COMPONENT_STATUS_END;
822 } else {
823 status = BT_COMPONENT_STATUS_ERROR;
824 }
825
826 end:
827 PyErr_Clear();
828 return status;
829 }
830
831 static enum bt_component_status bt_py3_cc_sink_consume(
832 struct bt_component *component)
833 {
834 PyObject *py_comp = bt_component_get_private_data(component);
835 PyObject *py_consume_method_result = NULL;
836 enum bt_component_status status;
837
838 py_consume_method_result = PyObject_CallMethod(py_comp,
839 "_consume", NULL);
840 status = bt_py3_exc_to_component_status();
841 if (!py_consume_method_result && status == BT_COMPONENT_STATUS_OK) {
842 /* Pretty sure this should never happen, but just in case */
843 status = BT_COMPONENT_STATUS_ERROR;
844 }
845
846 Py_XDECREF(py_consume_method_result);
847 return status;
848 }
849
850 static enum bt_component_status bt_py3_cc_sink_filter_add_iterator(
851 struct bt_component *component,
852 struct bt_notification_iterator *iter)
853 {
854 PyObject *py_comp = bt_component_get_private_data(component);
855 PyObject *py_add_iterator_method_result = NULL;
856 PyObject *py_notif_iter_ptr = NULL;
857 enum bt_component_status status;
858
859 py_notif_iter_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(iter),
860 SWIGTYPE_p_bt_notification_iterator, 0);
861 if (!py_notif_iter_ptr) {
862 PyErr_Clear();
863 status = BT_COMPONENT_STATUS_ERROR;
864 goto end;
865 }
866
867 bt_get(iter);
868 py_add_iterator_method_result = PyObject_CallMethod(py_comp,
869 "_add_iterator_from_bt", "(O)", py_notif_iter_ptr);
870 status = bt_py3_exc_to_component_status();
871 if (!py_add_iterator_method_result
872 && status == BT_COMPONENT_STATUS_OK) {
873 /* Pretty sure this should never happen, but just in case */
874 status = BT_COMPONENT_STATUS_ERROR;
875 }
876
877 end:
878 Py_XDECREF(py_notif_iter_ptr);
879 Py_XDECREF(py_add_iterator_method_result);
880 return status;
881 }
882
883
884 /* Component class creation functions (called from Python module) */
885
886 static int bt_py3_cc_set_optional_attrs_methods(struct bt_component_class *cc,
887 const char *description)
888 {
889 int ret = 0;
890
891 if (description) {
892 ret = bt_component_class_set_description(cc, description);
893 if (ret) {
894 goto end;
895 }
896 }
897
898 ret = bt_component_class_set_init_method(cc, bt_py3_cc_init);
899 if (ret) {
900 goto end;
901 }
902
903 ret = bt_component_class_set_destroy_method(cc, bt_py3_cc_destroy);
904 if (ret) {
905 goto end;
906 }
907
908 end:
909 return ret;
910 }
911
912 static int bt_py3_cc_set_optional_iter_methods(struct bt_component_class *cc,
913 bool has_seek_time,
914 int (*set_notif_iter_init_method)(struct bt_component_class *, bt_component_class_notification_iterator_init_method),
915 int (*set_notif_iter_destroy_method)(struct bt_component_class *, bt_component_class_notification_iterator_destroy_method),
916 int (*set_notif_iter_seek_time_method)(struct bt_component_class *, bt_component_class_notification_iterator_seek_time_method))
917 {
918 int ret;
919
920 ret = set_notif_iter_init_method(
921 cc, bt_py3_cc_notification_iterator_init);
922 if (ret) {
923 goto end;
924 }
925
926 ret = set_notif_iter_destroy_method(
927 cc, bt_py3_cc_notification_iterator_destroy);
928 if (ret) {
929 goto end;
930 }
931
932 if (has_seek_time) {
933 ret = set_notif_iter_seek_time_method(
934 cc, bt_py3_cc_notification_iterator_seek_time);
935 if (ret) {
936 goto end;
937 }
938 }
939
940 end:
941 return ret;
942 }
943
944 static struct bt_component_class *bt_py3_component_class_source_create(
945 PyObject *py_cls, const char *name, const char *description,
946 bool has_seek_time)
947 {
948 struct bt_component_class *cc;
949 int ret;
950
951 assert(py_cls);
952 cc = bt_component_class_source_create(name,
953 bt_py3_cc_notification_iterator_get,
954 bt_py3_cc_notification_iterator_next);
955 if (!cc) {
956 goto end;
957 }
958
959 ret = bt_py3_cc_set_optional_attrs_methods(cc, description);
960 if (ret) {
961 BT_PUT(cc);
962 goto end;
963 }
964
965 ret = bt_py3_cc_set_optional_iter_methods(cc, has_seek_time,
966 bt_component_class_source_set_notification_iterator_init_method,
967 bt_component_class_source_set_notification_iterator_destroy_method,
968 bt_component_class_source_set_notification_iterator_seek_time_method);
969 if (ret) {
970 BT_PUT(cc);
971 goto end;
972 }
973
974 register_cc_ptr_to_py_cls(cc, py_cls);
975 bt_component_class_freeze(cc);
976
977 end:
978 return cc;
979 }
980
981 static struct bt_component_class *bt_py3_component_class_filter_create(
982 PyObject *py_cls, const char *name, const char *description,
983 bool has_seek_time)
984 {
985 struct bt_component_class *cc;
986 int ret;
987
988 assert(py_cls);
989 cc = bt_component_class_filter_create(name,
990 bt_py3_cc_notification_iterator_get,
991 bt_py3_cc_notification_iterator_next);
992 if (!cc) {
993 goto end;
994 }
995
996 ret = bt_py3_cc_set_optional_attrs_methods(cc, description);
997 if (ret) {
998 BT_PUT(cc);
999 goto end;
1000 }
1001
1002 ret = bt_py3_cc_set_optional_iter_methods(cc, has_seek_time,
1003 bt_component_class_filter_set_notification_iterator_init_method,
1004 bt_component_class_filter_set_notification_iterator_destroy_method,
1005 bt_component_class_filter_set_notification_iterator_seek_time_method);
1006 if (ret) {
1007 BT_PUT(cc);
1008 goto end;
1009 }
1010
1011 ret = bt_component_class_filter_set_add_iterator_method(cc,
1012 bt_py3_cc_sink_filter_add_iterator);
1013 if (ret) {
1014 BT_PUT(cc);
1015 goto end;
1016 }
1017
1018 register_cc_ptr_to_py_cls(cc, py_cls);
1019 bt_component_class_freeze(cc);
1020
1021 end:
1022 return cc;
1023 }
1024
1025 static struct bt_component_class *bt_py3_component_class_sink_create(
1026 PyObject *py_cls, const char *name, const char *description)
1027 {
1028 struct bt_component_class *cc;
1029 int ret;
1030
1031 assert(py_cls);
1032 cc = bt_component_class_sink_create(name, bt_py3_cc_sink_consume);
1033 if (!cc) {
1034 goto end;
1035 }
1036
1037 ret = bt_py3_cc_set_optional_attrs_methods(cc, description);
1038 if (ret) {
1039 BT_PUT(cc);
1040 goto end;
1041 }
1042
1043 ret = bt_component_class_sink_set_add_iterator_method(cc,
1044 bt_py3_cc_sink_filter_add_iterator);
1045 if (ret) {
1046 BT_PUT(cc);
1047 goto end;
1048 }
1049
1050 register_cc_ptr_to_py_cls(cc, py_cls);
1051 bt_component_class_freeze(cc);
1052
1053 end:
1054 return cc;
1055 }
1056
1057
1058 /* Component creation function (called from Python module) */
1059
1060 static void bt_py3_component_create(
1061 struct bt_component_class *comp_class, PyObject *py_self,
1062 const char *name)
1063 {
1064 struct bt_component *component =
1065 bt_component_create_with_init_method_data(comp_class,
1066 name, NULL, py_self);
1067
1068 /*
1069 * Our component initialization function, bt_py3_cc_init(), sets
1070 * a new reference to the created component in the user's Python
1071 * object (py_self._ptr). This is where the reference is kept.
1072 * We don't need the returned component in this case (if any,
1073 * because it might be NULL if the creation failed, most
1074 * probably because py_self.__init__() raised something).
1075 */
1076 bt_put(component);
1077 }
1078
1079
1080 /* Component delete notification */
1081
1082 static void bt_py3_component_on_del(PyObject *py_comp)
1083 {
1084 /*
1085 * The Python component's __del__() function calls this to
1086 * indicate that there's no more reference on it from the
1087 * Python world.
1088 *
1089 * Since the BT component can continue to live once the Python
1090 * component object is deleted, we increment the Python
1091 * component's reference count so that it now only belong to the
1092 * BT component. We will decrement this reference count once
1093 * the BT component is destroyed in bt_py3_cc_destroy().
1094 */
1095 assert(py_comp);
1096 Py_INCREF(py_comp);
1097 }
1098 %}
1099
1100 %exception bt_py3_component_create {
1101 $action
1102 if (PyErr_Occurred()) {
1103 /* Exception is already set by bt_py3_component_create() */
1104 SWIG_fail;
1105 }
1106 }
1107
1108 struct bt_component_class *bt_py3_component_class_source_create(
1109 PyObject *py_cls, const char *name, const char *description,
1110 bool has_seek_time);
1111 struct bt_component_class *bt_py3_component_class_filter_create(
1112 PyObject *py_cls, const char *name, const char *description,
1113 bool has_seek_time);
1114 struct bt_component_class *bt_py3_component_class_sink_create(
1115 PyObject *py_cls, const char *name, const char *description);
1116 void bt_py3_component_create(
1117 struct bt_component_class *comp_class, PyObject *py_self,
1118 const char *name);
1119 void bt_py3_component_on_del(PyObject *py_comp);
1120 void bt_py3_cc_init_from_bt2(void);
1121 void bt_py3_cc_exit_handler(void);
This page took 0.052102 seconds and 4 git commands to generate.