I followed the gstreamer's tutorial on how to write plugins, and my goal is to create a video sink. For now I will just post relevant code, but if needed, I can upload whole plugin code somewhere. It will be an opensource anyway.
The class structure looks like this:
struct _GstIviOpenglSinkClass
{
GstVideoSinkClass base_iviopenglsink_class;
};
and my class_init() function looks like this:
static void
gst_iviopenglsink_class_init (GstIviOpenglSinkClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
GstBaseSinkClass *gstbasesink_class = GST_BASE_SINK_CLASS (klass);
GstVideoSinkClass *gstvideosink_class = GST_VIDEO_SINK_CLASS (klass);
GST_DEBUG ("START");
gobject_class->set_property = gst_iviopenglsink_set_property;
gobject_class->get_property = gst_iviopenglsink_get_property;
gobject_class->finalize = gst_iviopenglsink_finalize;
gst_element_class_add_pad_template (gstelement_class,
gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
gst_caps_from_string (VIDEO_SINK_CAPS)));
gst_element_class_set_static_metadata (gstelement_class,
"desc", "Sink/Video",
"desc",
"me <me#com.com>");
gstbasesink_class->get_caps = gst_iviopenglsink_get_caps;
gstbasesink_class->set_caps = gst_iviopenglsink_set_caps;
/* makes problems?!? */
gstelement_class->change_state = gst_iviopenglsink_change_state;
gstvideosink_class->show_frame = gst_iviopenglsink_show_frame;
GST_DEBUG ("END");
}
If I leave the class_init function like this, then the callbacks set_caps, get_caps, and show_frame, are not working (not being called at all). If I outcomment the assignment of the change_state, then these 3 callbacks are being called.
Am I doing something wrong in the class_init function, or is the problem lieing somewhere else? What can I do to debug this?
This comment was correct - the problem is indeed in the function dealing with change_state. I took a look into the source code for waylandsink and found this weird line:
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
I have no idea what that line is doing, but apparently it is needed. And it is nowhere explained neither in the tutorial for plugins, nor in the page describing GstElementClass.
If someone can explain why is that needed, I would really appreciate it :)
Related
I recently started working on a small driver for the raspberry pico and the bme280 sensor. I wanted to use the official bosh API written in C and therefore decided to write all the code in C using the micropython C api to write usermodules. I managed to get my code compiled into a UF2 file and my module shows up when I try to list the modules with help('modules'). When I import my module the class with the driver code shows up in dir(mymodule) but when I try to create an object the terminal connected to the PICO hangs and doesn't respond anymore.
typedef struct {
mp_obj_base_t base;
uint8_t sda;
uint8_t scl;
uint8_t i2c_address;
} BME280_obj_t;
const mp_obj_type_t BME280_class_type;
STATIC mp_obj_t BME280_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 2, 2, true);
BME280_obj_t* self = m_new_obj(BME280_obj_t);
self->base.type = &BME280_class_type;
self->sda = mp_obj_get_int(args[0]);
self->scl = mp_obj_get_int(args[1]);
self->i2c_address = n_args <= 2? BME280_I2C_ADDR_SEC : mp_obj_get_int(args[2]);
return MP_OBJ_FROM_PTR(self);
}
STATIC const mp_rom_map_elem_t BME280_locals_dict_table[] = {
// for testing purpose i removed all methods from the class
};
STATIC MP_DEFINE_CONST_DICT(BME280_locals_dict, BME280_locals_dict_table);
const mp_obj_type_t BME280_type = {
{ &mp_type_type },
.name = MP_QSTR_BME280,
.print = BME280_print,
.make_new = BME280_make_new,
.locals_dict = (mp_obj_dict_t*) &BME280_locals_dict,
};
STATIC const mp_rom_map_elem_t bme280_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bme280) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_BME280), (mp_obj_t)&BME280_class_type }
};
STATIC MP_DEFINE_CONST_DICT(bme280_module_globals, bme280_module_globals_table);
// module registration
const mp_obj_module_t bme280_user_cmodule = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&bme280_module_globals,
};
MP_REGISTER_MODULE(MP_QSTR_melopero_bme280, melopero_bme280_user_cmodule, 1);
I think the problem relies somewhere in the initialization procedure since it does not go further... Maybe there is something that micropython is doing behind the scenes that I'm ignoring. There is not so many documentation on writing usermodules in C... any help/hints/ideas are greatly apreciated :)
EDIT+ANSWER:
Yes I got the example to build and so I started to strip down my code to the minimum necessary to get it almost identical to the example and so I found the error...
The problem was that I used a different name for the class type in the declaration: BME280_class_type and in the definition: BME280_type
You have .print defined but it doesn't exist in your code.
const mp_obj_type_t BME280_type = {
{ &mp_type_type },
.name = MP_QSTR_BME280,
.print = BME280_print,
.make_new = BME280_make_new,
.locals_dict = (mp_obj_dict_t*) &BME280_locals_dict,
};
There is an example of writing a proper class print function here
However, this should be enough to at least satisfy the print requirement. Paste this into your code and see if it stops hanging.
STATIC void BME280_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
BME280_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_print_str(print, "BME280");
}
Also, I'm sure you just left this out of your example, otherwise you wouldn't have been able to build it, at all, but for the sake of being thorough ~ you have to include the proper header files.
#include <stdio.h>
#include "py/runtime.h"
#include "py/obj.h"
Edit: I was curious. You said you got everything to build, but it hangs. I commented out the print function for one of my C MODULE classes, and it would not build. This tells me that you (like the header) decided to just leave this part out of your example. This wastes time. How can you be helped if your example is creating errors that do not exist for you? However, even though this answer is now wrong, I am going to leave it up as an example of why answer-seekers shouldn't pick and choose what to post. Just post ALL of the relevant script to your problem and let us figure out the rest. I'd probably have an answer for you if I wasn't solving the wrong problem. Actually, I do see your problem, you're creating your module with mixed namespaces.
I'm using the C API of Z3. I've checked the examples, and Z3_mk_config() and Z3_mk_context (Z3_config c) are used to create contexts, e.g.,
Z3_config cfg;
Z3_context ctx;
cfg = Z3_mk_config();
Z3_set_param_value(cfg, "model", "true");
//...
ctx = Z3_mk_context(cfg);
However, the documentation says that all these functions are deprecated, but don't mention which functions should be used now instead.
Does anyone know which functions should be used now to create configurations and contexts?
Any help would be greatly appreciated. Thank you!
TLDR:
Use Z3_mk_config to create a Z3_config.
Use Z3_global_param_set to set configs globally.
Use Z3_set_param_value to set context-specific configs.
If you don't have any config to set, simply
make a Z3_config with Z3_mk_config,
create your context with it,
and then delete it with Z3_del_config.
The comment by SergeyLebedev is probably referencing to this remark in the doc
In previous versions of Z3, the Z3_config was used to store global and
module configurations. Now, we should use Z3_global_param_set.
I was going through the source repo the past few days. In the example file test_capi.c, they use this mk_context function a lot, which is defined in the same file with
Z3_context mk_context()
{
Z3_config cfg;
Z3_context ctx;
cfg = Z3_mk_config();
ctx = mk_context_custom(cfg, error_handler);
Z3_del_config(cfg);
return ctx;
}
where mk_context_custom is defined in the same file with
Z3_context mk_context_custom(Z3_config cfg, Z3_error_handler err)
{
Z3_context ctx;
Z3_set_param_value(cfg, "model", "true");
ctx = Z3_mk_context(cfg);
Z3_set_error_handler(ctx, err);
return ctx;
}
So it looks like Z3_mk_config and Z3_set_param_value are still used.
The doc says that stuff like Z3_config and Z3_context are supposed to be "opaque pointers". However, chasing it to the source, it looks like Z3_config is declared as a struct without the specific content but seems like wherever it's used it's cast to context_params which is defined clearly as a class.
The type Z3_config is declared in z3_api_h with
DEFINE_TYPE(Z3_config);
where DEFINE_TYPE(T) is a macro defined in z3_macros.h and expands to typedef struct _ ## T *T. So really Z3_config is only prototypically declared as a struct.
The function Z3_mk_config, the constructor for a Z3_config, declared in z3_api.h with
Z3_config Z3_API Z3_mk_config(void);
, is defined in api_config_params.cpp as
Z3_config Z3_API Z3_mk_config(void) {
try {
memory::initialize(UINT_MAX);
LOG_Z3_mk_config();
Z3_config r = reinterpret_cast<Z3_config>(alloc(context_params));
RETURN_Z3(r);
} catch (z3_exception & ex) {
// The error handler is only available for contexts
// Just throw a warning.
warning_msg("%s", ex.msg());
return nullptr;
}
}
within an extern "C" block. Note that Z3_API is a macro also defined in z3_macros.h to set __attribute__ ((visibility ("default"))) and alloc is a macro defined in memory_manager.h with #define alloc(T,...) new (memory::allocate(sizeof(T))) T(__VA_ARGS__) and RETURN_Z3 is a macro defined in some file generated by the file update_api.py with #define RETURN_Z3(Z3RES) if (_LOG_CTX.enabled()) { SetR(Z3RES); } return Z3RES.
It appears that, when a Z3_config is created, a memory block of the size of a context_params is allocated and cast as Z3_config, and context_params is in fact a class defined clearly in context_params.h. I omit the content because it's not relevant right now.
class context_params {
....
};
Next, Z3_set_param_value is defined in api_config_params.cpp with
void Z3_API Z3_set_param_value(Z3_config c, char const * param_id, char const * param_value) {
LOG_Z3_set_param_value(c, param_id, param_value);
try {
context_params * p = reinterpret_cast<context_params*>(c);
p->set(param_id, param_value);
}
catch (z3_exception & ex) {
// The error handler is only available for contexts
// Just throw a warning.
warning_msg("%s", ex.msg());
}
}
So it appears that the function first cast Z3_config back to context_params before using it like a normal object. I'm not an expert but this probably works because struct and class are almost the same underneath the hood.
On the other hand, in that exmaple file test_capi.c, they used Z3_global_param_set like so
....
cfg = Z3_mk_config();
....
/*
The current model finder for quantified formulas cannot handle injectivity.
So, we are limiting the number of iterations to avoid a long "wait".
*/
Z3_global_param_set("smt.mbqi.max_iterations", "10");
ctx = mk_context_custom(cfg, error_handler);
Z3_del_config(cfg);
s = mk_solver(ctx);
They did still use Z3_mk_config before making a context while using Z3_global_param_set to set configs. So I'd say there's nothing wrong with using Z3_mk_config to construct a Z3_config, and what the doc is saying is when you want to set something globally, don't access the Z3_config struct itself since you can't before casting it to a context_params anyway; use Z3_global_param_set instead. And when you want to set something specific to some specific context, use Z3_set_param_value.
The question remains that why would we want to switch between structs and classes? I don't know. I'm not at all familiar with C++, but I'm guessing, if not for the C API itself, it's for making the extern "C" part works for the Python API bindings.
I am working on a fairly simple application written in C with GTK+ that is leaking memory badly. It has a few basic functions on timers that check the clock and poll an external networked device, parsing the string returned. The application runs on a small touch panel, and through TOP I can watch the available memory be eaten up as it runs.
I'm pretty new to C, so not surprised that I'm doing something wrong, I just can't seem to figure out what. I've been trying to use Valgrind to narrow it down, but honestly the output is a little over my head (10k+ line log file generated from running the application less than a minute). But in digging through that log I did find some functions repeatedly showing up with permanently lost blocks, all using some similar structure.
Example 1:
This is a short function that gets called when an option is selected. The last line with the g_strdup_printf is the one called out by Valgrind. select_next_show and select_show_five_displayed are both global variables.
static void show_box_five_clicked ()
{
g_timer_start(lock_timer);
gtk_image_set_from_file (GTK_IMAGE(select_show_1_cb_image), "./images/checkbox_clear.png");
gtk_image_set_from_file (GTK_IMAGE(select_show_2_cb_image), "./images/checkbox_clear.png");
gtk_image_set_from_file (GTK_IMAGE(select_show_3_cb_image), "./images/checkbox_clear.png");
gtk_image_set_from_file (GTK_IMAGE(select_show_4_cb_image), "./images/checkbox_clear.png");
gtk_image_set_from_file (GTK_IMAGE(select_show_5_cb_image), "./images/checkbox_checked.png");
select_next_show = g_strdup_printf("%i",select_show_five_displayed);
}
Example 2:
This is another function that gets called often and came up a lot in the Valgrind log. It takes the incoming response from the networked device, parses it into two strings, then returns one.
static gchar* parse_incoming_value(gchar* incoming_message)
{
gchar *ret;
GString *incoming = g_string_new(incoming_message);
gchar **messagePieces = g_strsplit((char *)incoming->str, "=", 2);
ret = g_strdup(messagePieces[1]);
g_strfreev(messagePieces);
g_string_free(incoming, TRUE);
return ret;
}
In all the cases like these which are causing problems I'm freeing everything I can without causing segmentation faults, but I must be missing something else or doing something wrong.
UPDATE:
To answer questions in comments, here is an example (trimmed down) of how I'm using the parse function and where the return is freed:
static void load_schedule ()
{
...other code...
gchar *holder;
gchar *holder2;
holder = read_a_line(schedListenSocket);
holder2 = parse_incoming_value(holder);
schedule_info->regShowNumber = holder2;
holder = read_a_line(schedListenSocket);
holder2 = parse_incoming_value(holder);
schedule_info->holidayShowNumber = holder2;
...other code....
g_free(holder);
g_free(holder2);
}
Any help is greatly appreciated!!
It looks like you free 'ret' once when calling g_free(holder2), but you've done multiple allocations for that one free - you call parse_incoming_value multiple times, each time causing an allocation, but you only free once right at the end.
As you copy the holder2 pointer into schedule_info elements each time, they actually have the "leaked" memory at the end.
If you do not free holder2 anywhere, but just free all the elements in schedule_info at the end of the code. I presume that shows no leak?
e.g.
holder2 = <result of dynamic alloc>;
schedule_info->a = holder2;
...
holder2 = <result of dynamic alloc>;
schedule_info->b = holder2;
...
// instead of g_free(holder2) at the end, do this...
g_free(schedule_info->a);
g_free(schedule_info->a);
I'm trying to make a simple timer that fires a specific call back when its time come.
I have written this code:
void testTimer()
{
pj_timer_heap_t *timer_heap;
pj_timer_entry registrationTimer;
char *username="test_data";
pj_timer_entry_init(®istrationTimer, 50, username, &on_timer_event);
pj_time_val delay;
delay.sec = 5;
delay.msec = 0;
pj_status_t status = pj_timer_heap_create(global.pool, 256, &timer_heap);
status=pj_timer_heap_schedule(timer_heap,®istrationTimer, &delay);
}
I don't know whats wrong with the code. This code crashes on pj_timer_heap_schedule.I am unable to figure out whats missing. Pls Help.
It's a little impossible to know the problem without the
pj_timer_heap_schedule
function
Try and initialize as
`pj_bzero(®istrationTimer, sizeof(registrationTimer));`
then ensure you have done
`registrationTimer.id = PJSUA_INVALID_ID;`
`registrationTimer.cb = &my_callback;`
finally don't forget to define and declare your callback my_callback
Good luck
When list of stations is printed in Preset rol list and you are at the begining or at the end of the list, you see many empty items.
I create list of about 20 stations and try to display them, go to the begining and to the end of the list.
I think the problem is in this piece of code:
static void add_button_clicked_cb(GtkWidget *widget, gpointer data)
{
preset *ps;
gchar *buffer;
GtkTreeIter iter = {0};
GtkAdjustment* v_scb;
GtkTreePath *path = NULL;
GList* menuitems;
GtkWidget *menuitem;
ps = malloc(sizeof(preset));
ps->title = g_strdup(_("unnamed"));
ps->freq = rint(gtk_adjustment_get_value(adj)) / STEPS;
settings.presets = g_list_append(settings.presets, (gpointer) ps);
buffer = g_strdup_printf("%.2f", ps->freq);
gtk_list_store_append(list_store, &iter);
gtk_list_store_set(list_store, &iter, 0, ps->title, 1, buffer, -1);
g_free(buffer);
gtk_tree_selection_unselect_all(selection);
v_scb = gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(list_view));
gtk_adjustment_set_value(v_scb, gtk_adjustment_get_upper(v_scb));
if (main_visible) {
gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(preset_combo), ps->title);
mom_ps = g_list_length(settings.presets) - 1;
preset_combo_set_item(mom_ps);
menuitems = gtk_container_get_children(GTK_CONTAINER(tray_menu));
menuitem = gtk_menu_item_new_with_label(ps->title);
gtk_menu_shell_insert(GTK_MENU_SHELL(tray_menu), menuitem, mom_ps);
g_signal_connect(G_OBJECT(menuitem), "activate", (GCallback)preset_menuitem_activate_cb, (gpointer)mom_ps);
gtk_widget_show(menuitem);
}
buffer = g_strdup_printf("%d", g_list_length(settings.presets) - 1);
path = gtk_tree_path_new_from_string(buffer);
g_free(buffer);
gtk_tree_view_set_cursor(GTK_TREE_VIEW(list_view), path, NULL, FALSE);
gtk_tree_path_free(path);
}
Could you please suggest me how can correct it?
Inside of the if (main_visible), you have:
menuitems = gtk_container_get_children(GTK_CONTAINER(tray_menu));
That is, you're setting the value of menuitems to the return value of that function call. However, none of the rest of your code actually does anything with menuitems. So, the compiler gives you that warning.
Fixing it might be as easy as simply getting rid of menuitems:
gtk_container_get_children(GTK_CONTAINER(tray_menu));
That would definitely get rid of the warning. But you have to think about it: Maybe you should be doing something with the return value of that function call, and the reason that you're not doing anything with it is that you forgot to (or whatever).
warning: variable 'menuitems' set but not used
Your compiler in layman's terms is saying the following:
Dude... youve created a class with a few attributes, one of which are called 'menuitems'. That's all well mate, but when you actually create an instance and assign all the variables, youve set 'menuitems' but youre never using that variable to do anything with it. its just sitting there doing nothing at all. So mate it's no problem at all as I can still run your program but im just warning you that the 'menuitems' variable is doing ** all as you're never using the variable itself. Just warning you bro :D other than that have a good day
So its just a warning to let you know you have a variable no being used for any specific reason other than storing a value in there but never accessing it to do something useful. So either comment it out since youre not actually doing anything with it.. or use it, or just enjoy reading the warning but it wont affect the way your program runs.
The warnings get displayed mainly to get the developer more aware of their own code and whats happening.