Martin Fischer
Martin Fischer

Reputation: 697

C LIBCHAMPLAIN SegFault?

I had a programm with C and libchamplain which showed a map. worked fine. Now i wanted to integrate it into an gtk application. But at running, i get a segfault:

#include <stdio.h>
#include <gtk/gtk.h>
#include <champlain/champlain.h>
#include <champlain-gtk/champlain-gtk.h>
#include <clutter-gtk/clutter-gtk.h>
#include <math.h>

#include "GPS_stub.h"

#define MARKER_SIZE 10
#define MAX_SIZ 4096

static gboolean draw_center(ClutterCanvas *canvas, cairo_t *cr, int width, int height){
  cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
  cairo_paint(cr);
  cairo_set_operator(cr, CAIRO_OPERATOR_OVER);

  cairo_set_source_rgb(cr, 0, 0, 0);
  cairo_arc(cr, MARKER_SIZE / 2.0, MARKER_SIZE / 2.0, MARKER_SIZE / 2.0, 0, 2 * M_PI);
  cairo_close_path(cr);
  cairo_set_source_rgba(cr, 0.1, 0.1, 0.9, 1.0);
  cairo_fill(cr);

  return TRUE;
}

static ClutterActor *create_marker(void){
  ClutterActor *marker;
  ClutterActor *bg;
  ClutterContent *canvas;
  ClutterTransition *transition;

  marker = champlain_custom_marker_new();

  canvas = clutter_canvas_new();
  clutter_canvas_set_size(CLUTTER_CANVAS(canvas), MARKER_SIZE, MARKER_SIZE);
  g_signal_connect(canvas, "draw", G_CALLBACK(draw_center), NULL);

  bg = clutter_actor_new();
  clutter_actor_set_size(bg, MARKER_SIZE, MARKER_SIZE);
  clutter_actor_set_content(bg, canvas);
  clutter_content_invalidate(canvas);
  g_object_unref(canvas);

  clutter_actor_add_child(marker, bg);
  clutter_actor_set_pivot_point(bg, 0.5, 0.5);
  clutter_actor_set_position(bg, -MARKER_SIZE, -MARKER_SIZE);

  transition = clutter_property_transition_new("opacity");
  clutter_actor_set_easing_mode(bg, CLUTTER_EASE_OUT_SINE);
  clutter_timeline_set_duration(CLUTTER_TIMELINE(transition), 1000);
  clutter_timeline_set_repeat_count(CLUTTER_TIMELINE(transition), -1);
  clutter_transition_set_from(transition, G_TYPE_UINT, 255);
  clutter_transition_set_to(transition, G_TYPE_UINT, 0);
  clutter_actor_add_transition(bg, "animate-opacity", transition);

  transition = clutter_property_transition_new("scale-x");
  clutter_actor_set_easing_mode(bg, CLUTTER_EASE_OUT_SINE);
  clutter_timeline_set_duration(CLUTTER_TIMELINE(transition), 1000);
  clutter_timeline_set_repeat_count(CLUTTER_TIMELINE(transition), -1);
  clutter_transition_set_from(transition, G_TYPE_FLOAT, 0.5);
  clutter_transition_set_to(transition, G_TYPE_FLOAT, 1.0);
  clutter_actor_add_transition(bg, "animate-scale-x", transition);

  transition = clutter_property_transition_new("scale-y");
  clutter_actor_set_easing_mode(bg, CLUTTER_EASE_OUT_SINE);
  clutter_timeline_set_duration(CLUTTER_TIMELINE(transition), 1000);
  clutter_timeline_set_repeat_count(CLUTTER_TIMELINE(transition), -1);
  clutter_transition_set_from(transition, G_TYPE_FLOAT, 0.5);
  clutter_transition_set_to(transition, G_TYPE_FLOAT, 1.0);
  clutter_actor_add_transition(bg, "animate-scale-y", transition);

  return marker;
}

static gboolean gps_callback(ChamplainMarker *marker[MAX_SIZ]){
  return TRUE;
}

typedef struct{
  double lat;
  double lng;
} GpsCallbackData;

static void load_map(GpsCallbackData *data){
  ClutterActor *actor, *stage;
  ChamplainMarkerLayer *layer;
  ClutterActor *marker[MAX_SIZ];

  stage = clutter_stage_new();
  clutter_actor_set_size(stage, 800, 600);
  g_signal_connect(stage, "destroy", G_CALLBACK(clutter_main_quit), NULL);

  actor = champlain_view_new();
  clutter_actor_set_size(CLUTTER_ACTOR(actor), 800, 600);
  clutter_actor_add_child(stage, actor);

  layer = champlain_marker_layer_new_full(CHAMPLAIN_SELECTION_SINGLE);
  clutter_actor_show(CLUTTER_ACTOR(layer));
  champlain_view_add_layer(CHAMPLAIN_VIEW(actor), CHAMPLAIN_LAYER(layer));

  for(int i = 0; i < MAX_SIZ/40; i++){
    marker[i] = create_marker();
    champlain_marker_layer_add_marker(layer, CHAMPLAIN_MARKER(marker[i]));
    champlain_location_set_location(CHAMPLAIN_LOCATION(marker[i]), data->lat+i/10, data->lng+i/10);
  }

  g_object_set(G_OBJECT(actor), "zoom-level", 2, "kinetic-mode", TRUE, NULL);
  champlain_view_center_on(CHAMPLAIN_VIEW(actor), 40, 0);

  g_timeout_add(1000, (GSourceFunc) gps_callback, CHAMPLAIN_MARKER(marker));

  clutter_actor_show(stage);
  clutter_main();
}

int main(int argc, char *argv[]){
  GtkWidget *window, *button;

  GpsCallbackData *gps;

  double lat, lng;

  gtk_clutter_init(&argc, &argv);
  hs_init(&argc, &argv);

  getGPS("166.82.21.200", &lat, &lng);
  printf("GPS: %f %f\n", lat, lng);

  gps->lat = lat;
  gps->lng = lng;

  window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
  gtk_container_set_border_width(GTK_CONTAINER(window), 10);

  button = gtk_button_new_with_label("Load Map");
  g_signal_connect(button, "clicked", G_CALLBACK(load_map), &gps);

  gtk_container_add(GTK_CONTAINER(window), button);
  gtk_widget_show(window);
  gtk_main();

  hs_exit();

  return 0;
}

like you can see in main , it prints out coordinates. This works fine. But then after the printing i'm getting an segfault.

Why?

Upvotes: 1

Views: 58

Answers (1)

Myoungje Kim
Myoungje Kim

Reputation: 11

I have a same problem on ARM Linux from here.

 stage = clutter_stage_new();
 clutter_actor_set_size(stage, 800, 600);

When I removed or blocked "clutter_actor_set", there's no seg fault error.

actor is O.K, but stage is matter. But on X86 Ubuntu desktop, it's O.K.

Upvotes: 1

Related Questions