lib: rename INVALID_OBJECT status to UNKNOWN_OBJECT
[babeltrace.git] / src / bindings / python / bt2 / bt2 / native_bt_component_class.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 %include <babeltrace2/graph/component-class.h>
26 %include <babeltrace2/graph/component-class-const.h>
27 %include <babeltrace2/graph/component-class-source-const.h>
28 %include <babeltrace2/graph/component-class-source.h>
29 %include <babeltrace2/graph/component-class-filter-const.h>
30 %include <babeltrace2/graph/component-class-filter.h>
31 %include <babeltrace2/graph/component-class-sink-const.h>
32 %include <babeltrace2/graph/component-class-sink.h>
33 %include <babeltrace2/graph/self-component-class-source.h>
34 %include <babeltrace2/graph/self-component-class-filter.h>
35 %include <babeltrace2/graph/self-component-class-sink.h>
36
37 %{
38 /*
39 * This hash table associates a BT component class object address to a
40 * user-defined Python class (PyObject *). The keys and values are NOT
41 * owned by this hash table. The Python class objects are owned by the
42 * Python module, which should not be unloaded until it is not possible
43 * to create a user Python component anyway.
44 *
45 * This hash table is written to when a user-defined Python component
46 * class is created by one of the bt_bt2_component_class_*_create()
47 * functions.
48 *
49 * This function is read from when a user calls bt_component_create()
50 * with a component class pointer created by one of the functions above.
51 * In this case, the original Python class needs to be found to
52 * instantiate it and associate the created Python component object with
53 * a BT component object instance.
54 */
55
56 static GHashTable *bt_cc_ptr_to_py_cls;
57
58 static
59 void register_cc_ptr_to_py_cls(struct bt_component_class *bt_cc,
60 PyObject *py_cls)
61 {
62 if (!bt_cc_ptr_to_py_cls) {
63 /*
64 * Lazy-initializing this GHashTable because GLib
65 * might not be initialized yet and it needs to be
66 * before we call g_hash_table_new()
67 */
68 BT_LOGD_STR("Creating native component class to Python component class hash table.");
69 bt_cc_ptr_to_py_cls = g_hash_table_new(g_direct_hash, g_direct_equal);
70 BT_ASSERT(bt_cc_ptr_to_py_cls);
71 }
72
73 g_hash_table_insert(bt_cc_ptr_to_py_cls, (gpointer) bt_cc,
74 (gpointer) py_cls);
75 }
76
77 static
78 PyObject *lookup_cc_ptr_to_py_cls(const bt_component_class *bt_cc)
79 {
80 if (!bt_cc_ptr_to_py_cls) {
81 BT_LOGW("Cannot look up Python component class because hash table is NULL: "
82 "comp-cls-addr=%p", bt_cc);
83 return NULL;
84 }
85
86 return (PyObject *) g_hash_table_lookup(bt_cc_ptr_to_py_cls,
87 (gconstpointer) bt_cc);
88 }
89
90
91 /*
92 * Useful Python objects.
93 */
94
95 static PyObject *py_mod_bt2 = NULL;
96 static PyObject *py_mod_bt2_exc_error_type = NULL;
97 static PyObject *py_mod_bt2_exc_memory_error = NULL;
98 static PyObject *py_mod_bt2_exc_try_again_type = NULL;
99 static PyObject *py_mod_bt2_exc_stop_type = NULL;
100 static PyObject *py_mod_bt2_exc_unknown_object_type = NULL;
101
102 static
103 void bt_bt2_cc_init_from_bt2(void)
104 {
105 /*
106 * This is called once the bt2 package is loaded.
107 *
108 * Those modules and functions are needed while the package is
109 * used. Loading them here is safe because we know the bt2
110 * package is imported, and we know that the user cannot use the
111 * code here without importing bt2 first.
112 */
113 py_mod_bt2 = PyImport_ImportModule("bt2");
114 BT_ASSERT(py_mod_bt2);
115 py_mod_bt2_exc_error_type =
116 PyObject_GetAttrString(py_mod_bt2, "_Error");
117 BT_ASSERT(py_mod_bt2_exc_error_type);
118 py_mod_bt2_exc_memory_error =
119 PyObject_GetAttrString(py_mod_bt2, "_MemoryError");
120 BT_ASSERT(py_mod_bt2_exc_memory_error);
121 py_mod_bt2_exc_try_again_type =
122 PyObject_GetAttrString(py_mod_bt2, "TryAgain");
123 BT_ASSERT(py_mod_bt2_exc_try_again_type);
124 py_mod_bt2_exc_stop_type =
125 PyObject_GetAttrString(py_mod_bt2, "Stop");
126 BT_ASSERT(py_mod_bt2_exc_stop_type);
127 py_mod_bt2_exc_unknown_object_type =
128 PyObject_GetAttrString(py_mod_bt2, "UnknownObject");
129 BT_ASSERT(py_mod_bt2_exc_unknown_object_type);
130 }
131
132 static
133 void bt_bt2_cc_exit_handler(void)
134 {
135 /*
136 * This is an exit handler (set by the bt2 package).
137 *
138 * We only give back the references that we took in
139 * bt_bt2_cc_init_from_bt2() here. The global variables continue
140 * to exist for the code of this file, but they are now borrowed
141 * references. If this code is executed, it means that somehow
142 * the modules are still loaded, so it should be safe to use
143 * them even without a strong reference.
144 *
145 * We cannot do this in the library's destructor because it
146 * gets executed once Python is already finalized.
147 */
148 Py_XDECREF(py_mod_bt2);
149 Py_XDECREF(py_mod_bt2_exc_error_type);
150 Py_XDECREF(py_mod_bt2_exc_try_again_type);
151 Py_XDECREF(py_mod_bt2_exc_stop_type);
152 Py_XDECREF(py_mod_bt2_exc_unknown_object_type);
153 }
154
155
156 /* Library destructor */
157
158 __attribute__((destructor))
159 static
160 void native_comp_class_dtor(void) {
161 /* Destroy component class association hash table */
162 if (bt_cc_ptr_to_py_cls) {
163 BT_LOGD_STR("Destroying native component class to Python component class hash table.");
164 g_hash_table_destroy(bt_cc_ptr_to_py_cls);
165 }
166 }
167
168 static
169 void restore_current_thread_error_and_append_exception_chain_recursive(
170 PyObject *py_exc_value,
171 bt_self_component_class *self_component_class,
172 bt_self_component *self_component,
173 bt_self_message_iterator *self_message_iterator,
174 const char *module_name)
175 {
176 PyObject *py_exc_cause_value;
177 PyObject *py_exc_type = NULL;
178 PyObject *py_exc_tb = NULL;
179 GString *gstr = NULL;
180
181 /* If this exception has a cause, handle that one first. */
182 py_exc_cause_value = PyException_GetCause(py_exc_value);
183 if (py_exc_cause_value) {
184 restore_current_thread_error_and_append_exception_chain_recursive(
185 py_exc_cause_value, self_component_class,
186 self_component, self_message_iterator, module_name);
187 }
188
189 /*
190 * If the raised exception is a bt2._Error, restore the wrapped error.
191 */
192 if (PyErr_GivenExceptionMatches(py_exc_value, py_mod_bt2_exc_error_type)) {
193 PyObject *py_error_swig_ptr;
194 const bt_error *error;
195 int ret;
196
197 /*
198 * We never raise a bt2._Error with a cause: it should be the
199 * end of the chain.
200 */
201 BT_ASSERT(!py_exc_cause_value);
202
203 /*
204 * We steal the error object from the exception, to move
205 * it back as the current thread's error.
206 */
207 py_error_swig_ptr = PyObject_GetAttrString(py_exc_value, "_ptr");
208 BT_ASSERT(py_error_swig_ptr);
209
210 ret = PyObject_SetAttrString(py_exc_value, "_ptr", Py_None);
211 BT_ASSERT(ret == 0);
212
213 ret = SWIG_ConvertPtr(py_error_swig_ptr, (void **) &error,
214 SWIGTYPE_p_bt_error, 0);
215 BT_ASSERT(ret == 0);
216
217 BT_CURRENT_THREAD_MOVE_ERROR_AND_RESET(error);
218
219 Py_DECREF(py_error_swig_ptr);
220 }
221
222 py_exc_type = PyObject_Type(py_exc_value);
223 py_exc_tb = PyException_GetTraceback(py_exc_value);
224
225 gstr = bt_py_common_format_exception(py_exc_type, py_exc_value,
226 py_exc_tb, BT_LOG_OUTPUT_LEVEL, false);
227 if (!gstr) {
228 /* bt_py_common_format_exception has already warned. */
229 goto end;
230 }
231
232 if (self_component_class) {
233 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT_CLASS(
234 self_component_class, "%s", gstr->str);
235 } else if (self_component) {
236 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_COMPONENT(
237 self_component, "%s", gstr->str);
238 } else if (self_message_iterator) {
239 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_MESSAGE_ITERATOR(
240 self_message_iterator, "%s", gstr->str);
241 } else {
242 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(
243 module_name, "%s", gstr->str);
244 }
245
246 end:
247 if (gstr) {
248 g_string_free(gstr, TRUE);
249 }
250
251 Py_XDECREF(py_exc_cause_value);
252 Py_XDECREF(py_exc_type);
253 Py_XDECREF(py_exc_tb);
254 }
255
256 /*
257 * If you have the following code:
258 *
259 * try:
260 * try:
261 * something_that_raises_bt2_error()
262 * except bt2._Error as e1:
263 * raise ValueError from e1
264 * except ValueError as e2:
265 * raise TypeError from e2
266 *
267 * We will have the following exception chain:
268 *
269 * TypeError -> ValueError -> bt2._Error
270 *
271 * Where the TypeError is the current exception (obtained from PyErr_Fetch).
272 *
273 * The bt2._Error contains a `struct bt_error *` that used to be the current
274 * thread's error, at the moment the exception was raised.
275 *
276 * This function gets to the bt2._Error and restores the wrapped
277 * `struct bt_error *` as the current thread's error.
278 *
279 * Then, for each exception in the chain, starting with the oldest one, it adds
280 * an error cause to the current thread's error.
281 */
282 static
283 void restore_bt_error_and_append_current_exception_chain(
284 bt_self_component_class *self_component_class,
285 bt_self_component *self_component,
286 bt_self_message_iterator *self_message_iterator,
287 const char *module_name)
288 {
289 BT_ASSERT(PyErr_Occurred());
290
291 /* Used to access and restore the current exception. */
292 PyObject *py_exc_type;
293 PyObject *py_exc_value;
294 PyObject *py_exc_tb;
295
296 /* Fetch and normalize the Python exception. */
297 PyErr_Fetch(&py_exc_type, &py_exc_value, &py_exc_tb);
298 PyErr_NormalizeException(&py_exc_type, &py_exc_value, &py_exc_tb);
299 BT_ASSERT(py_exc_type);
300 BT_ASSERT(py_exc_value);
301 BT_ASSERT(py_exc_tb);
302
303 /*
304 * Set the exception's traceback so it's possible to get it using
305 * PyException_GetTraceback in
306 * restore_current_thread_error_and_append_exception_chain_recursive.
307 */
308 PyException_SetTraceback(py_exc_value, py_exc_tb);
309
310 restore_current_thread_error_and_append_exception_chain_recursive(py_exc_value,
311 self_component_class, self_component, self_message_iterator,
312 module_name);
313
314 PyErr_Restore(py_exc_type, py_exc_value, py_exc_tb);
315 }
316
317 static inline
318 void log_exception_and_maybe_append_error(int log_level,
319 bool append_error,
320 bt_self_component_class *self_component_class,
321 bt_self_component *self_component,
322 bt_self_message_iterator *self_message_iterator,
323 const char *module_name)
324 {
325 GString *gstr;
326
327 BT_ASSERT(PyErr_Occurred());
328 gstr = bt_py_common_format_current_exception(BT_LOG_OUTPUT_LEVEL);
329 if (!gstr) {
330 /* bt_py_common_format_current_exception() logs errors */
331 goto end;
332 }
333
334 BT_LOG_WRITE(log_level, BT_LOG_TAG, "%s", gstr->str);
335
336 if (append_error) {
337 restore_bt_error_and_append_current_exception_chain(
338 self_component_class, self_component,
339 self_message_iterator, module_name);
340
341 }
342
343 end:
344 if (gstr) {
345 g_string_free(gstr, TRUE);
346 }
347 }
348
349 static inline
350 void loge_exception(const char *module_name)
351 {
352 log_exception_and_maybe_append_error(BT_LOG_ERROR, true, NULL, NULL,
353 NULL, module_name);
354 }
355
356 static
357 void loge_exception_message_iterator(
358 bt_self_message_iterator *self_message_iterator)
359 {
360 log_exception_and_maybe_append_error(BT_LOG_ERROR, true, NULL, NULL,
361 self_message_iterator, NULL);
362 }
363
364 static inline
365 void logw_exception(void)
366 {
367 log_exception_and_maybe_append_error(BT_LOG_WARNING, false, NULL, NULL,
368 NULL, NULL);
369 }
370
371 static inline
372 int py_exc_to_status(bt_self_component_class *self_component_class,
373 bt_self_component *self_component,
374 bt_self_message_iterator *self_message_iterator,
375 const char *module_name)
376 {
377 int status = __BT_FUNC_STATUS_OK;
378 PyObject *exc = PyErr_Occurred();
379
380 if (!exc) {
381 goto end;
382 }
383
384 if (PyErr_GivenExceptionMatches(exc,
385 py_mod_bt2_exc_try_again_type)) {
386 status = __BT_FUNC_STATUS_AGAIN;
387 } else if (PyErr_GivenExceptionMatches(exc,
388 py_mod_bt2_exc_stop_type)) {
389 status = __BT_FUNC_STATUS_END;
390 } else if (PyErr_GivenExceptionMatches(exc,
391 py_mod_bt2_exc_unknown_object_type)) {
392 status = __BT_FUNC_STATUS_UNKNOWN_OBJECT;
393 } else {
394 /* Unknown exception: convert to general error */
395 log_exception_and_maybe_append_error(BT_LOG_WARNING, true,
396 self_component_class, self_component,
397 self_message_iterator, module_name);
398
399 if (PyErr_GivenExceptionMatches(exc,
400 py_mod_bt2_exc_memory_error)) {
401 status = __BT_FUNC_STATUS_MEMORY_ERROR;
402 } else {
403 status = __BT_FUNC_STATUS_ERROR;
404 }
405 }
406
407 end:
408 PyErr_Clear();
409 return status;
410 }
411
412 static
413 int py_exc_to_status_component_class(bt_self_component_class *self_component_class)
414 {
415 return py_exc_to_status(self_component_class, NULL, NULL, NULL);
416 }
417
418 static
419 int py_exc_to_status_component(bt_self_component *self_component)
420 {
421 return py_exc_to_status(NULL, self_component, NULL, NULL);
422 }
423
424 static
425 int py_exc_to_status_message_iterator(
426 bt_self_message_iterator *self_message_iterator)
427 {
428 return py_exc_to_status(NULL, NULL, self_message_iterator, NULL);
429 }
430
431 /* Component class proxy methods (delegate to the attached Python object) */
432
433 static
434 bt_component_class_init_method_status component_class_init(
435 bt_self_component *self_component,
436 void *self_component_v,
437 swig_type_info *self_comp_cls_type_swig_type,
438 const bt_value *params,
439 void *init_method_data)
440 {
441 const bt_component *component = bt_self_component_as_component(self_component);
442 const bt_component_class *component_class = bt_component_borrow_class_const(component);
443 bt_component_class_init_method_status status = __BT_FUNC_STATUS_OK;
444 PyObject *py_cls = NULL;
445 PyObject *py_comp = NULL;
446 PyObject *py_params_ptr = NULL;
447 PyObject *py_comp_ptr = NULL;
448
449 (void) init_method_data;
450
451 BT_ASSERT(self_component);
452 BT_ASSERT(self_component_v);
453 BT_ASSERT(self_comp_cls_type_swig_type);
454
455 /*
456 * Get the user-defined Python class which created this
457 * component's class in the first place (borrowed
458 * reference).
459 */
460 py_cls = lookup_cc_ptr_to_py_cls(component_class);
461 if (!py_cls) {
462 BT_LOGE("Cannot find Python class associated to native component class: "
463 "comp-cls-addr=%p", component_class);
464 goto error;
465 }
466
467 /* Parameters pointer -> SWIG pointer Python object */
468 py_params_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(params),
469 SWIGTYPE_p_bt_value, 0);
470 if (!py_params_ptr) {
471 BT_LOGE_STR("Failed to create a SWIG pointer object.");
472 goto error;
473 }
474
475 py_comp_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(self_component_v),
476 self_comp_cls_type_swig_type, 0);
477 if (!py_comp_ptr) {
478 BT_LOGE_STR("Failed to create a SWIG pointer object.");
479 goto error;
480 }
481
482 /*
483 * Do the equivalent of this:
484 *
485 * py_comp = py_cls._bt_init_from_native(py_comp_ptr, py_params_ptr)
486 *
487 * _UserComponentType._bt_init_from_native() calls the Python
488 * component object's __init__() function.
489 */
490 py_comp = PyObject_CallMethod(py_cls,
491 "_bt_init_from_native", "(OO)", py_comp_ptr, py_params_ptr);
492 if (!py_comp) {
493 BT_LOGW("Failed to call Python class's _bt_init_from_native() method: "
494 "py-cls-addr=%p", py_cls);
495 status = py_exc_to_status_component(self_component);
496 goto end;
497 }
498
499 /*
500 * Our user Python component object is now fully created and
501 * initialized by the user. Since we just created it, this
502 * native component is its only (persistent) owner.
503 */
504 bt_self_component_set_data(self_component, py_comp);
505 py_comp = NULL;
506 goto end;
507
508 error:
509 status = __BT_FUNC_STATUS_ERROR;
510
511 /*
512 * Clear any exception: we're returning a bad status anyway. If
513 * this call originated from Python (creation from a plugin's
514 * component class, for example), then the user gets an
515 * appropriate creation error.
516 */
517 PyErr_Clear();
518
519 end:
520 Py_XDECREF(py_comp);
521 Py_XDECREF(py_params_ptr);
522 Py_XDECREF(py_comp_ptr);
523 return status;
524 }
525
526 /*
527 * Method of bt_component_class_source to initialize a bt_self_component_source
528 * of that class.
529 */
530
531 static
532 bt_component_class_init_method_status component_class_source_init(
533 bt_self_component_source *self_component_source,
534 const bt_value *params, void *init_method_data)
535 {
536 bt_self_component *self_component = bt_self_component_source_as_self_component(self_component_source);
537 return component_class_init(
538 self_component,
539 self_component_source,
540 SWIGTYPE_p_bt_self_component_source,
541 params, init_method_data);
542 }
543
544 static
545 bt_component_class_init_method_status component_class_filter_init(
546 bt_self_component_filter *self_component_filter,
547 const bt_value *params, void *init_method_data)
548 {
549 bt_self_component *self_component = bt_self_component_filter_as_self_component(self_component_filter);
550 return component_class_init(
551 self_component,
552 self_component_filter,
553 SWIGTYPE_p_bt_self_component_filter,
554 params, init_method_data);
555 }
556
557 static
558 bt_component_class_init_method_status component_class_sink_init(
559 bt_self_component_sink *self_component_sink,
560 const bt_value *params, void *init_method_data)
561 {
562 bt_self_component *self_component = bt_self_component_sink_as_self_component(self_component_sink);
563 return component_class_init(
564 self_component,
565 self_component_sink,
566 SWIGTYPE_p_bt_self_component_sink,
567 params, init_method_data);
568 }
569
570 static
571 void component_class_finalize(bt_self_component *self_component)
572 {
573 PyObject *py_comp = bt_self_component_get_data(self_component);
574 BT_ASSERT(py_comp);
575
576 /* Call user's _user_finalize() method */
577 PyObject *py_method_result = PyObject_CallMethod(py_comp,
578 "_user_finalize", NULL);
579
580 if (PyErr_Occurred()) {
581 BT_LOGW("User component's _user_finalize() method raised an exception: ignoring:");
582 logw_exception();
583 }
584
585 /*
586 * Ignore any exception raised by the _user_finalize() method
587 * because it won't change anything at this point: the component
588 * is being destroyed anyway.
589 */
590 PyErr_Clear();
591 Py_XDECREF(py_method_result);
592 Py_DECREF(py_comp);
593 }
594
595 static
596 void component_class_source_finalize(bt_self_component_source *self_component_source)
597 {
598 bt_self_component *self_component = bt_self_component_source_as_self_component(self_component_source);
599 component_class_finalize(self_component);
600 }
601
602 static
603 void component_class_filter_finalize(bt_self_component_filter *self_component_filter)
604 {
605 bt_self_component *self_component = bt_self_component_filter_as_self_component(self_component_filter);
606 component_class_finalize(self_component);
607 }
608
609 static
610 void component_class_sink_finalize(bt_self_component_sink *self_component_sink)
611 {
612 bt_self_component *self_component = bt_self_component_sink_as_self_component(self_component_sink);
613 component_class_finalize(self_component);
614 }
615
616 static
617 bt_bool component_class_can_seek_beginning(
618 bt_self_message_iterator *self_message_iterator)
619 {
620 PyObject *py_iter;
621 PyObject *py_result = NULL;
622 bt_bool can_seek_beginning = false;
623
624 py_iter = bt_self_message_iterator_get_data(self_message_iterator);
625 BT_ASSERT(py_iter);
626
627 py_result = PyObject_GetAttrString(py_iter, "_bt_can_seek_beginning_from_native");
628
629 BT_ASSERT(!py_result || PyBool_Check(py_result));
630
631 if (py_result) {
632 can_seek_beginning = PyObject_IsTrue(py_result);
633 } else {
634 /*
635 * Once can_seek_beginning can report errors, convert the
636 * exception to a status. For now, log and return false;
637 */
638 loge_exception_message_iterator(self_message_iterator);
639 PyErr_Clear();
640 }
641
642 Py_XDECREF(py_result);
643
644 return can_seek_beginning;
645 }
646
647 static
648 bt_component_class_message_iterator_seek_beginning_method_status
649 component_class_seek_beginning(bt_self_message_iterator *self_message_iterator)
650 {
651 PyObject *py_iter;
652 PyObject *py_result;
653 bt_component_class_message_iterator_seek_beginning_method_status status;
654
655 py_iter = bt_self_message_iterator_get_data(self_message_iterator);
656 BT_ASSERT(py_iter);
657 py_result = PyObject_CallMethod(py_iter, "_bt_seek_beginning_from_native",
658 NULL);
659 BT_ASSERT(!py_result || py_result == Py_None);
660 status = py_exc_to_status_message_iterator(self_message_iterator);
661 Py_XDECREF(py_result);
662 return status;
663 }
664
665 static
666 bt_component_class_port_connected_method_status component_class_port_connected(
667 bt_self_component *self_component,
668 void *self_component_port,
669 swig_type_info *self_component_port_swig_type,
670 bt_port_type self_component_port_type,
671 const void *other_port,
672 swig_type_info *other_port_swig_type)
673 {
674 bt_component_class_port_connected_method_status status;
675 PyObject *py_comp = NULL;
676 PyObject *py_self_port_ptr = NULL;
677 PyObject *py_other_port_ptr = NULL;
678 PyObject *py_method_result = NULL;
679
680 py_comp = bt_self_component_get_data(self_component);
681 BT_ASSERT(py_comp);
682 py_self_port_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(self_component_port),
683 self_component_port_swig_type, 0);
684 if (!py_self_port_ptr) {
685 BT_LOGF_STR("Failed to create a SWIG pointer object.");
686 status = __BT_FUNC_STATUS_MEMORY_ERROR;
687 goto end;
688 }
689
690 py_other_port_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(other_port),
691 other_port_swig_type, 0);
692 if (!py_other_port_ptr) {
693 BT_LOGF_STR("Failed to create a SWIG pointer object.");
694 status = __BT_FUNC_STATUS_MEMORY_ERROR;
695 goto end; }
696
697 py_method_result = PyObject_CallMethod(py_comp,
698 "_bt_port_connected_from_native", "(OiO)", py_self_port_ptr,
699 self_component_port_type, py_other_port_ptr);
700 BT_ASSERT(!py_method_result || py_method_result == Py_None);
701 status = py_exc_to_status_component(self_component);
702
703 end:
704 Py_XDECREF(py_self_port_ptr);
705 Py_XDECREF(py_other_port_ptr);
706 Py_XDECREF(py_method_result);
707 return status;
708 }
709
710 static
711 bt_component_class_port_connected_method_status
712 component_class_source_output_port_connected(
713 bt_self_component_source *self_component_source,
714 bt_self_component_port_output *self_component_port_output,
715 const bt_port_input *other_port_input)
716 {
717 bt_self_component *self_component = bt_self_component_source_as_self_component(self_component_source);
718
719 return component_class_port_connected(
720 self_component,
721 self_component_port_output,
722 SWIGTYPE_p_bt_self_component_port_output,
723 BT_PORT_TYPE_OUTPUT,
724 other_port_input,
725 SWIGTYPE_p_bt_port_input);
726 }
727
728 static
729 bt_component_class_port_connected_method_status
730 component_class_filter_input_port_connected(
731 bt_self_component_filter *self_component_filter,
732 bt_self_component_port_input *self_component_port_input,
733 const bt_port_output *other_port_output)
734 {
735 bt_self_component *self_component = bt_self_component_filter_as_self_component(self_component_filter);
736
737 return component_class_port_connected(
738 self_component,
739 self_component_port_input,
740 SWIGTYPE_p_bt_self_component_port_input,
741 BT_PORT_TYPE_INPUT,
742 other_port_output,
743 SWIGTYPE_p_bt_port_output);
744 }
745
746 static
747 bt_component_class_port_connected_method_status
748 component_class_filter_output_port_connected(
749 bt_self_component_filter *self_component_filter,
750 bt_self_component_port_output *self_component_port_output,
751 const bt_port_input *other_port_input)
752 {
753 bt_self_component *self_component = bt_self_component_filter_as_self_component(self_component_filter);
754
755 return component_class_port_connected(
756 self_component,
757 self_component_port_output,
758 SWIGTYPE_p_bt_self_component_port_output,
759 BT_PORT_TYPE_OUTPUT,
760 other_port_input,
761 SWIGTYPE_p_bt_port_input);
762 }
763
764 static
765 bt_component_class_port_connected_method_status
766 component_class_sink_input_port_connected(
767 bt_self_component_sink *self_component_sink,
768 bt_self_component_port_input *self_component_port_input,
769 const bt_port_output *other_port_output)
770 {
771 bt_self_component *self_component = bt_self_component_sink_as_self_component(self_component_sink);
772
773 return component_class_port_connected(
774 self_component,
775 self_component_port_input,
776 SWIGTYPE_p_bt_self_component_port_input,
777 BT_PORT_TYPE_INPUT,
778 other_port_output,
779 SWIGTYPE_p_bt_port_output);
780 }
781
782 static
783 bt_component_class_sink_graph_is_configured_method_status
784 component_class_sink_graph_is_configured(
785 bt_self_component_sink *self_component_sink)
786 {
787 PyObject *py_comp = NULL;
788 PyObject *py_method_result = NULL;
789 bt_component_class_sink_graph_is_configured_method_status status = __BT_FUNC_STATUS_OK;
790 bt_self_component *self_component = bt_self_component_sink_as_self_component(self_component_sink);
791
792 py_comp = bt_self_component_get_data(self_component);
793 py_method_result = PyObject_CallMethod(py_comp,
794 "_bt_graph_is_configured_from_native", NULL);
795 BT_ASSERT(!py_method_result || py_method_result == Py_None);
796 status = py_exc_to_status_component(self_component);
797 Py_XDECREF(py_method_result);
798 return status;
799 }
800
801 static
802 bt_component_class_query_method_status component_class_query(
803 const bt_component_class *component_class,
804 bt_self_component_class *self_component_class,
805 const bt_query_executor *query_executor,
806 const char *object, const bt_value *params,
807 bt_logging_level log_level,
808 const bt_value **result)
809 {
810 PyObject *py_cls = NULL;
811 PyObject *py_params_ptr = NULL;
812 PyObject *py_query_exec_ptr = NULL;
813 PyObject *py_query_func = NULL;
814 PyObject *py_object = NULL;
815 PyObject *py_results_addr = NULL;
816 bt_component_class_query_method_status status = __BT_FUNC_STATUS_OK;
817
818 py_cls = lookup_cc_ptr_to_py_cls(component_class);
819 if (!py_cls) {
820 BT_LOGE("Cannot find Python class associated to native component class: "
821 "comp-cls-addr=%p", component_class);
822 goto error;
823 }
824
825 py_params_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(params),
826 SWIGTYPE_p_bt_value, 0);
827 if (!py_params_ptr) {
828 BT_LOGE_STR("Failed to create a SWIG pointer object.");
829 goto error;
830 }
831
832 py_query_exec_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(query_executor),
833 SWIGTYPE_p_bt_query_executor, 0);
834 if (!py_query_exec_ptr) {
835 BT_LOGE_STR("Failed to create a SWIG pointer object.");
836 goto error;
837 }
838
839 py_object = SWIG_FromCharPtr(object);
840 if (!py_object) {
841 BT_LOGE_STR("Failed to create a Python string.");
842 goto error;
843 }
844
845 py_results_addr = PyObject_CallMethod(py_cls,
846 "_bt_query_from_native", "(OOOi)", py_query_exec_ptr,
847 py_object, py_params_ptr, (int) log_level);
848 if (!py_results_addr) {
849 BT_LOGW("Failed to call Python class's _bt_query_from_native() method: "
850 "py-cls-addr=%p", py_cls);
851 status = py_exc_to_status_component_class(self_component_class);
852 goto end;
853 }
854
855 /*
856 * The returned object, on success, is an integer object
857 * (PyLong) containing the address of a BT value object (new
858 * reference).
859 */
860 *result = PyLong_AsVoidPtr(py_results_addr);
861 BT_ASSERT(!PyErr_Occurred());
862 BT_ASSERT(*result);
863 goto end;
864
865 error:
866 PyErr_Clear();
867 status = __BT_FUNC_STATUS_ERROR;
868
869 end:
870 Py_XDECREF(py_params_ptr);
871 Py_XDECREF(py_query_exec_ptr);
872 Py_XDECREF(py_query_func);
873 Py_XDECREF(py_object);
874 Py_XDECREF(py_results_addr);
875 return status;
876 }
877
878 static
879 bt_component_class_query_method_status component_class_source_query(
880 bt_self_component_class_source *self_component_class_source,
881 const bt_query_executor *query_executor,
882 const char *object, const bt_value *params,
883 bt_logging_level log_level,
884 const bt_value **result)
885 {
886 const bt_component_class_source *component_class_source = bt_self_component_class_source_as_component_class_source(self_component_class_source);
887 const bt_component_class *component_class = bt_component_class_source_as_component_class_const(component_class_source);
888 bt_self_component_class *self_component_class = bt_self_component_class_source_as_self_component_class(self_component_class_source);
889
890 return component_class_query(component_class, self_component_class, query_executor, object, params, log_level, result);
891 }
892
893 static
894 bt_component_class_query_method_status component_class_filter_query(
895 bt_self_component_class_filter *self_component_class_filter,
896 const bt_query_executor *query_executor,
897 const char *object, const bt_value *params,
898 bt_logging_level log_level,
899 const bt_value **result)
900 {
901 const bt_component_class_filter *component_class_filter = bt_self_component_class_filter_as_component_class_filter(self_component_class_filter);
902 const bt_component_class *component_class = bt_component_class_filter_as_component_class_const(component_class_filter);
903 bt_self_component_class *self_component_class = bt_self_component_class_filter_as_self_component_class(self_component_class_filter);
904
905 return component_class_query(component_class, self_component_class, query_executor, object, params, log_level, result);
906 }
907
908 static
909 bt_component_class_query_method_status component_class_sink_query(
910 bt_self_component_class_sink *self_component_class_sink,
911 const bt_query_executor *query_executor,
912 const char *object, const bt_value *params,
913 bt_logging_level log_level,
914 const bt_value **result)
915 {
916 const bt_component_class_sink *component_class_sink = bt_self_component_class_sink_as_component_class_sink(self_component_class_sink);
917 const bt_component_class *component_class = bt_component_class_sink_as_component_class_const(component_class_sink);
918 bt_self_component_class *self_component_class = bt_self_component_class_sink_as_self_component_class(self_component_class_sink);
919
920 return component_class_query(component_class, self_component_class, query_executor, object, params, log_level, result);
921 }
922
923 static
924 bt_component_class_message_iterator_init_method_status
925 component_class_message_iterator_init(
926 bt_self_message_iterator *self_message_iterator,
927 bt_self_component *self_component,
928 bt_self_component_port_output *self_component_port_output)
929 {
930 bt_component_class_message_iterator_init_method_status status = __BT_FUNC_STATUS_OK;
931 PyObject *py_comp_cls = NULL;
932 PyObject *py_iter_cls = NULL;
933 PyObject *py_iter_ptr = NULL;
934 PyObject *py_component_port_output_ptr = NULL;
935 PyObject *py_init_method_result = NULL;
936 PyObject *py_iter = NULL;
937 PyObject *py_comp;
938
939 py_comp = bt_self_component_get_data(self_component);
940
941 /* Find user's Python message iterator class */
942 py_comp_cls = PyObject_GetAttrString(py_comp, "__class__");
943 if (!py_comp_cls) {
944 BT_LOGE_STR("Cannot get Python object's `__class__` attribute.");
945 goto python_error;
946 }
947
948 py_iter_cls = PyObject_GetAttrString(py_comp_cls, "_iter_cls");
949 if (!py_iter_cls) {
950 BT_LOGE_STR("Cannot get Python class's `_iter_cls` attribute.");
951 goto python_error;
952 }
953
954 py_iter_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(self_message_iterator),
955 SWIGTYPE_p_bt_self_message_iterator, 0);
956 if (!py_iter_ptr) {
957 const char *err = "Failed to create a SWIG pointer object.";
958
959 BT_LOGE_STR(err);
960 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_MESSAGE_ITERATOR(
961 self_message_iterator, err);
962 goto error;
963 }
964
965 /*
966 * Create object with borrowed native message iterator
967 * reference:
968 *
969 * py_iter = py_iter_cls.__new__(py_iter_cls, py_iter_ptr)
970 */
971 py_iter = PyObject_CallMethod(py_iter_cls, "__new__",
972 "(OO)", py_iter_cls, py_iter_ptr);
973 if (!py_iter) {
974 BT_LOGE("Failed to call Python class's __new__() method: "
975 "py-cls-addr=%p", py_iter_cls);
976 goto python_error;
977 }
978
979 /*
980 * Initialize object:
981 *
982 * py_iter.__init__(self_output_port)
983 *
984 * through the _init_for_native helper static method.
985 *
986 * At this point, py_iter._ptr is set, so this initialization
987 * function has access to self._component (which gives it the
988 * user Python component object from which the iterator was
989 * created).
990 */
991 py_component_port_output_ptr = SWIG_NewPointerObj(
992 SWIG_as_voidptr(self_component_port_output),
993 SWIGTYPE_p_bt_self_component_port_output, 0);
994 if (!py_component_port_output_ptr) {
995 const char *err = "Failed to create a SWIG pointer object.";
996
997 BT_LOGE_STR(err);
998 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_MESSAGE_ITERATOR(
999 self_message_iterator, err);
1000 goto error;
1001 }
1002
1003 py_init_method_result = PyObject_CallMethod(py_iter,
1004 "_bt_init_from_native", "O", py_component_port_output_ptr);
1005 if (!py_init_method_result) {
1006 BT_LOGE_STR("User's __init__() method failed:");
1007 goto python_error;
1008 }
1009
1010 /*
1011 * Since the Python code can never instantiate a user-defined
1012 * message iterator class, the native message iterator
1013 * object does NOT belong to a user Python message iterator
1014 * object (borrowed reference). However this Python object is
1015 * owned by this native message iterator object.
1016 *
1017 * In the Python world, the lifetime of the native message
1018 * iterator is managed by a _GenericMessageIterator
1019 * instance:
1020 *
1021 * _GenericMessageIterator instance:
1022 * owns a native bt_message_iterator object (iter)
1023 * owns a _UserMessageIterator instance (py_iter)
1024 * self._ptr is a borrowed reference to the
1025 * native bt_private_connection_private_message_iterator
1026 * object (iter)
1027 */
1028 bt_self_message_iterator_set_data(self_message_iterator, py_iter);
1029 py_iter = NULL;
1030 goto end;
1031
1032 python_error:
1033 /* Handling of errors that cause a Python exception to be set. */
1034 status = py_exc_to_status_message_iterator(self_message_iterator);
1035 BT_ASSERT(status != __BT_FUNC_STATUS_OK);
1036 goto end;
1037
1038 error:
1039 /* Handling of errors that don't cause a Python exception to be set. */
1040 status = __BT_FUNC_STATUS_ERROR;
1041
1042 end:
1043 BT_ASSERT(!PyErr_Occurred());
1044
1045 Py_XDECREF(py_comp_cls);
1046 Py_XDECREF(py_iter_cls);
1047 Py_XDECREF(py_iter_ptr);
1048 Py_XDECREF(py_component_port_output_ptr);
1049 Py_XDECREF(py_init_method_result);
1050 Py_XDECREF(py_iter);
1051 return status;
1052 }
1053
1054 static
1055 bt_component_class_message_iterator_init_method_status
1056 component_class_source_message_iterator_init(
1057 bt_self_message_iterator *self_message_iterator,
1058 bt_self_component_source *self_component_source,
1059 bt_self_component_port_output *self_component_port_output)
1060 {
1061 bt_self_component *self_component = bt_self_component_source_as_self_component(self_component_source);
1062
1063 return component_class_message_iterator_init(self_message_iterator, self_component, self_component_port_output);
1064 }
1065
1066 static
1067 bt_component_class_message_iterator_init_method_status
1068 component_class_filter_message_iterator_init(
1069 bt_self_message_iterator *self_message_iterator,
1070 bt_self_component_filter *self_component_filter,
1071 bt_self_component_port_output *self_component_port_output)
1072 {
1073 bt_self_component *self_component = bt_self_component_filter_as_self_component(self_component_filter);
1074
1075 return component_class_message_iterator_init(self_message_iterator, self_component, self_component_port_output);
1076 }
1077
1078 static
1079 void component_class_message_iterator_finalize(
1080 bt_self_message_iterator *message_iterator)
1081 {
1082 PyObject *py_message_iter = bt_self_message_iterator_get_data(message_iterator);
1083 PyObject *py_method_result = NULL;
1084
1085 BT_ASSERT(py_message_iter);
1086
1087 /* Call user's _user_finalize() method */
1088 py_method_result = PyObject_CallMethod(py_message_iter,
1089 "_user_finalize", NULL);
1090
1091 if (PyErr_Occurred()) {
1092 BT_LOGW("User's _user_finalize() method raised an exception: ignoring:");
1093 logw_exception();
1094 }
1095
1096 /*
1097 * Ignore any exception raised by the _user_finalize() method
1098 * because it won't change anything at this point: the component
1099 * is being destroyed anyway.
1100 */
1101 PyErr_Clear();
1102 Py_XDECREF(py_method_result);
1103 Py_DECREF(py_message_iter);
1104 }
1105
1106 /* Valid for both sources and filters. */
1107
1108 static
1109 bt_component_class_message_iterator_next_method_status
1110 component_class_message_iterator_next(
1111 bt_self_message_iterator *message_iterator,
1112 bt_message_array_const msgs, uint64_t capacity,
1113 uint64_t *count)
1114 {
1115 bt_component_class_message_iterator_next_method_status status = __BT_FUNC_STATUS_OK;
1116 PyObject *py_message_iter = bt_self_message_iterator_get_data(message_iterator);
1117 PyObject *py_method_result = NULL;
1118
1119 BT_ASSERT(py_message_iter);
1120 py_method_result = PyObject_CallMethod(py_message_iter,
1121 "_bt_next_from_native", NULL);
1122 if (!py_method_result) {
1123 status = py_exc_to_status_message_iterator(message_iterator);
1124 BT_ASSERT(status != __BT_FUNC_STATUS_OK);
1125 goto end;
1126 }
1127
1128 /*
1129 * The returned object, on success, is an integer object
1130 * (PyLong) containing the address of a native message
1131 * object (which is now ours).
1132 */
1133 msgs[0] = PyLong_AsVoidPtr(py_method_result);
1134 *count = 1;
1135
1136 /* Clear potential overflow error; should never happen */
1137 BT_ASSERT(!PyErr_Occurred());
1138 goto end;
1139
1140 end:
1141 Py_XDECREF(py_method_result);
1142 return status;
1143 }
1144
1145 static
1146 bt_component_class_sink_consume_method_status
1147 component_class_sink_consume(bt_self_component_sink *self_component_sink)
1148 {
1149 bt_self_component *self_component = bt_self_component_sink_as_self_component(self_component_sink);
1150 PyObject *py_comp = bt_self_component_get_data(self_component);
1151 PyObject *py_method_result = NULL;
1152 bt_component_class_sink_consume_method_status status;
1153
1154 BT_ASSERT(py_comp);
1155 py_method_result = PyObject_CallMethod(py_comp,
1156 "_user_consume", NULL);
1157 status = py_exc_to_status_component(self_component);
1158 if (!py_method_result && status == __BT_FUNC_STATUS_OK) {
1159 /* Pretty sure this should never happen, but just in case */
1160 BT_LOGE("User's _user_consume() method failed without raising an exception: "
1161 "status=%d", status);
1162 status = __BT_FUNC_STATUS_ERROR;
1163 }
1164
1165 Py_XDECREF(py_method_result);
1166 return status;
1167 }
1168
1169 static
1170 int component_class_set_help_and_desc(
1171 bt_component_class *component_class,
1172 const char *description, const char *help)
1173 {
1174 int ret;
1175
1176 if (description) {
1177 ret = bt_component_class_set_description(component_class, description);
1178 if (ret) {
1179 BT_LOGE("Cannot set component class's description: "
1180 "comp-cls-addr=%p", component_class);
1181 goto end;
1182 }
1183 }
1184
1185 if (help) {
1186 ret = bt_component_class_set_help(component_class, help);
1187 if (ret) {
1188 BT_LOGE("Cannot set component class's help text: "
1189 "comp-cls-addr=%p", component_class);
1190 goto end;
1191 }
1192 }
1193
1194 ret = 0;
1195
1196 end:
1197 return ret;
1198 }
1199
1200 static
1201 bt_component_class_source *bt_bt2_component_class_source_create(
1202 PyObject *py_cls, const char *name, const char *description,
1203 const char *help)
1204 {
1205 bt_component_class_source *component_class_source;
1206 bt_component_class *component_class;
1207 int ret;
1208
1209 BT_ASSERT(py_cls);
1210 component_class_source = bt_component_class_source_create(name,
1211 component_class_message_iterator_next);
1212 if (!component_class_source) {
1213 BT_LOGE_STR("Cannot create source component class.");
1214 goto end;
1215 }
1216
1217 component_class = bt_component_class_source_as_component_class(component_class_source);
1218
1219 if (component_class_set_help_and_desc(component_class, description, help)) {
1220 goto end;
1221 }
1222
1223 ret = bt_component_class_source_set_init_method(component_class_source, component_class_source_init);
1224 BT_ASSERT(ret == 0);
1225 ret = bt_component_class_source_set_finalize_method(component_class_source, component_class_source_finalize);
1226 BT_ASSERT(ret == 0);
1227 ret = bt_component_class_source_set_message_iterator_can_seek_beginning_method(component_class_source,
1228 component_class_can_seek_beginning);
1229 BT_ASSERT(ret == 0);
1230 ret = bt_component_class_source_set_message_iterator_seek_beginning_method(component_class_source,
1231 component_class_seek_beginning);
1232 BT_ASSERT(ret == 0);
1233 ret = bt_component_class_source_set_output_port_connected_method(component_class_source,
1234 component_class_source_output_port_connected);
1235 BT_ASSERT(ret == 0);
1236 ret = bt_component_class_source_set_query_method(component_class_source, component_class_source_query);
1237 BT_ASSERT(ret == 0);
1238 ret = bt_component_class_source_set_message_iterator_init_method(
1239 component_class_source, component_class_source_message_iterator_init);
1240 BT_ASSERT(ret == 0);
1241 ret = bt_component_class_source_set_message_iterator_finalize_method(
1242 component_class_source, component_class_message_iterator_finalize);
1243 BT_ASSERT(ret == 0);
1244 register_cc_ptr_to_py_cls(component_class, py_cls);
1245
1246 end:
1247 return component_class_source;
1248 }
1249
1250 static
1251 bt_component_class_filter *bt_bt2_component_class_filter_create(
1252 PyObject *py_cls, const char *name, const char *description,
1253 const char *help)
1254 {
1255 bt_component_class *component_class;
1256 bt_component_class_filter *component_class_filter;
1257 int ret;
1258
1259 BT_ASSERT(py_cls);
1260 component_class_filter = bt_component_class_filter_create(name,
1261 component_class_message_iterator_next);
1262 if (!component_class_filter) {
1263 BT_LOGE_STR("Cannot create filter component class.");
1264 goto end;
1265 }
1266
1267 component_class = bt_component_class_filter_as_component_class(component_class_filter);
1268
1269 if (component_class_set_help_and_desc(component_class, description, help)) {
1270 goto end;
1271 }
1272
1273 ret = bt_component_class_filter_set_init_method(component_class_filter, component_class_filter_init);
1274 BT_ASSERT(ret == 0);
1275 ret = bt_component_class_filter_set_finalize_method (component_class_filter, component_class_filter_finalize);
1276 BT_ASSERT(ret == 0);
1277 ret = bt_component_class_filter_set_message_iterator_can_seek_beginning_method(component_class_filter,
1278 component_class_can_seek_beginning);
1279 BT_ASSERT(ret == 0);
1280 ret = bt_component_class_filter_set_message_iterator_seek_beginning_method(component_class_filter,
1281 component_class_seek_beginning);
1282 BT_ASSERT(ret == 0);
1283 ret = bt_component_class_filter_set_input_port_connected_method(component_class_filter,
1284 component_class_filter_input_port_connected);
1285 BT_ASSERT(ret == 0);
1286 ret = bt_component_class_filter_set_output_port_connected_method(component_class_filter,
1287 component_class_filter_output_port_connected);
1288 BT_ASSERT(ret == 0);
1289 ret = bt_component_class_filter_set_query_method(component_class_filter, component_class_filter_query);
1290 BT_ASSERT(ret == 0);
1291 ret = bt_component_class_filter_set_message_iterator_init_method(
1292 component_class_filter, component_class_filter_message_iterator_init);
1293 BT_ASSERT(ret == 0);
1294 ret = bt_component_class_filter_set_message_iterator_finalize_method(
1295 component_class_filter, component_class_message_iterator_finalize);
1296 BT_ASSERT(ret == 0);
1297 register_cc_ptr_to_py_cls(component_class, py_cls);
1298
1299 end:
1300 return component_class_filter;
1301 }
1302
1303 static
1304 bt_component_class_sink *bt_bt2_component_class_sink_create(
1305 PyObject *py_cls, const char *name, const char *description,
1306 const char *help)
1307 {
1308 bt_component_class_sink *component_class_sink;
1309 bt_component_class *component_class;
1310 int ret;
1311
1312 BT_ASSERT(py_cls);
1313 component_class_sink = bt_component_class_sink_create(name, component_class_sink_consume);
1314
1315 if (!component_class_sink) {
1316 BT_LOGE_STR("Cannot create sink component class.");
1317 goto end;
1318 }
1319
1320 component_class = bt_component_class_sink_as_component_class(component_class_sink);
1321
1322 if (component_class_set_help_and_desc(component_class, description, help)) {
1323 goto end;
1324 }
1325
1326 ret = bt_component_class_sink_set_init_method(component_class_sink, component_class_sink_init);
1327 BT_ASSERT(ret == 0);
1328 ret = bt_component_class_sink_set_finalize_method(component_class_sink, component_class_sink_finalize);
1329 BT_ASSERT(ret == 0);
1330 ret = bt_component_class_sink_set_input_port_connected_method(component_class_sink,
1331 component_class_sink_input_port_connected);
1332 BT_ASSERT(ret == 0);
1333 ret = bt_component_class_sink_set_graph_is_configured_method(component_class_sink,
1334 component_class_sink_graph_is_configured);
1335 BT_ASSERT(ret == 0);
1336 ret = bt_component_class_sink_set_query_method(component_class_sink, component_class_sink_query);
1337 BT_ASSERT(ret == 0);
1338 register_cc_ptr_to_py_cls(component_class, py_cls);
1339
1340 end:
1341 return component_class_sink;
1342 }
1343 %}
1344
1345 struct bt_component_class_source *bt_bt2_component_class_source_create(
1346 PyObject *py_cls, const char *name, const char *description,
1347 const char *help);
1348 struct bt_component_class_filter *bt_bt2_component_class_filter_create(
1349 PyObject *py_cls, const char *name, const char *description,
1350 const char *help);
1351 struct bt_component_class_sink *bt_bt2_component_class_sink_create(
1352 PyObject *py_cls, const char *name, const char *description,
1353 const char *help);
1354 void bt_bt2_cc_init_from_bt2(void);
1355 void bt_bt2_cc_exit_handler(void);
This page took 0.084531 seconds and 4 git commands to generate.