Re: [Vala] struct value boxing in GLib.Array

I can't find a way to do what you want. Generics in vala is based on the
idea that the type should fit into a 32 bit pointer, so int32 ok, int64 not
ok. Hence the requirement to box some types. Unfortunately this just doesn't
work too well with something like GLib.Array. The second nail in the coffin,
so to speak, is that struct returns in vala are done via a pointer passed
into the method. g_array_index returns an l-value of the actual array entry.
Nice for C code, but not for codegen.

Is it possible for you to use a vanilla array, such as Point[]  ?

On 21 July 2011 02:21, Jan Spurny <JSpurny seznam cz> wrote:


I have some trouble with using one C library which is using value-copied
structs inside GLib.Array container. Here is a small piece of code to
illustrate the problem:

#include "x.h"
GArray* get_array() {
  GArray *result = g_array_new(FALSE, FALSE, sizeof(Point));
  Point a = { 1, 2 };
  Point b = { 3, 5 };
  g_array_append_val(result, a);
  g_array_append_val(result, b);
  return result;

#include <glib.h>
typedef struct Point_ Point;
struct Point_ {
 int x;
 int y;
GArray* get_array();

[CCode (cheader_filename = "x.h")]
public struct Point {
 public int x;
 public int y;

[CCode (cheader_filename = "x.h")]
public GLib.Array<Point> get_array();

void main (string[] args)
   var pts = get_array();
   for (int i = 0 ; i < pts.length; i++) {
       var p = pts.index(i);
       stdout.printf(@"pt: $(p.x), $(p.y)\n");

(compile: "valac -X -I. --vapidir=. --pkg glib-2.0 --pkg x -o pgm pgm.vala

 x.vapi:9.19-9.23: error: `Point' is not a supported generic type argument,
use `?' to box value types
 public GLib.Array<Point> get_array();
But when I change the line in VAPI file to "public GLib.Array<Point?>
get_array();" it DOES COMPILE, but it doesn't work.
The resulting binary segfaults when executed because the generated C file
"thinks" the type in the GLib.Array is "Point*", but it is in fact "Point" -
see the generated C code:

void _vala_main (gchar** args, int args_length1) {
       GArray* _tmp0_ = NULL;
       GArray* pts;
       _tmp0_ = get_array ();
       pts = _tmp0_;
               gint i;
               i = 0;
                       gboolean _tmp1_;
                       _tmp1_ = TRUE;
                       while (TRUE) {
                               Point* _tmp2_ = NULL;
                               Point* _tmp3_;
                               Point* p;
                               _tmp2_ = g_array_index (pts, Point*, (guint)
                               _tmp3_ = __point_dup0 (_tmp2_);
                               p = _tmp3_;

I would very much prefer to keep the C library (the example above is only
an example, the real C library is quite large) and solve the problem on the
"vala side".. does anyone have any suggestions?

Thanks for any help.

Jan Spurny
vala-list mailing list
vala-list gnome org

Michael Brown

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]