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



Hi,

that's what I was affraid of - unfortunately the actual library I was talking about uses GArray this way in a 
lot of places, and to make things worse it is usually found as a value of a GHastTable.. anyway - I see no 
other way than to write helper function which would return normal array, as you've suggested. Something like:

void *array_from_garray(GArray *array, gsize *ret_size)
{
  *ret_size = array->len;
  return array->data;
}

which makes me wonder - the "data" field should be public, therefore I should be able to acces them inside 
Vala if I add the "data" field to the glib VAPI, right? But I'm affraid that's not something most people 
would want to see there :(

Anyway, thanks for help!

Regards,
Jan Spurny

 ------------ Původní zpráva ------------
 Od: Michael Brown <michael supersoftcafe com>
 Předmět: Re: [Vala] struct value boxing in GLib.Array
 Datum: 21.7.2011 11:54:50
 ----------------------------------------
 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:

 > Hi,
 >
 > 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:
 >
 > x.c
 > --------------------------------------
 > #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;
 > }
 > --------------------------------------
 >
 > x.h:
 > --------------------------------------
 > #include <glib.h>
 > typedef struct Point_ Point;
 > struct Point_ {
 >  int x;
 >  int y;
 > };
 > GArray* get_array();
 > --------------------------------------
 >
 > x.vapi:
 > --------------------------------------
 > [SimpleType]
 > [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();
 > --------------------------------------
 >
 > pgm.vala:
 > --------------------------------------
 > 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.c")
 >
 > Now it DOES NOT COMPILE:
 >  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)
 > i);
 >                                _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.
 >
 >
 > Regards,
 > Jan Spurny
 > _______________________________________________
 > vala-list mailing list
 > vala-list gnome org
 > http://mail.gnome.org/mailman/listinfo/vala-list
 >



 --
 Michael Brown






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