Re: [Vala] Variable sized structs and vapi files



Hi,

On Tue, 2009-09-15 at 09:06 +0200, Jan Hudec wrote:
On Tue, September 15, 2009 00:09, Jan-Jaap van der Geer wrote:
I wonder how to "vapify" a struct that has a variable part at the
end, such as the wimp_menu below (somewhat simplyfied):

struct wimp_menu_entry
   {  wimp_menu_flags menu_flags;
      wimp_menu *sub_menu;
   };

#define wimp_MENU_MEMBERS \
   int width; \
   int height;

struct wimp_menu
   {  wimp_MENU_MEMBERS
      wimp_menu_entry entries [UNKNOWN];
   };

UNKNOWN is defined to be 1, but the intended structure can be any
length, dependent on what is apropriate. It is actually recommended
to use a macro for defining the structure:

#define wimp_MENU(N) \
   struct \
      {  wimp_MENU_MEMBERS \
         wimp_menu_entry entries [N]; \
      }

I wonder how to do this. Somehow Vala needs to know how to allocate
and free the memory for these structures, so I suppose it somehow
needs to be told - but I do not know how.

Any ideas?

YUCK! Many objects in GLib are actually allocated with different size
than declared, but it is always hidden in allocator functions.

I see several options:

 1) Get the C API redefined to use:

    struct wimp_menu {
        int width;
        int height;
        wimp_menu_entry *entries;
    };

Not an option. The API is a very thin C layer to the operating system
(RISC OS) that wants memoryblocks that look like this. So any changes in
this department would mean the thin layer is not thin anymore and
changing either the library or the OS would of course break lots of
existing programs.

If you're really interested, see
http://www.drobe.co.uk/show_manual.php?manual=/sh-cgi?manual=Wimp%
26page=Wimp_CreateMenu

 2) Get a dynamic allocator into the API. It should look like:

    wimp_menu_entry_new(int n);

    or better

    wimp_menu_entry_new(int n, wimp_menu_entry[] entries);

    (where the entries will be copied to the allocated structure)
    Than you can bind the wimp_menu_entry as a [Compact] class and bind
    this method as it's constructor. If you get the later, you can bind
    it as

    [Compact]
    public class Menu {
        ...
        public Menu([CCode(array_length_pos = 0.9)] MenuEntry[] entries);
        ...

What does the array_length_pos = 0.9 mean?

    A delete function does not need to be defined, because you can easily
    specify
    [CCode(free_function = "free")]
    (or g_free, depending on whether it will be allocated with malloc or
    g_malloc)
    on the class definition.

A good solution, but it means changing the library and I don't think the
maintainers of the library will be very interested in taking in
functions like this. I suppose I could compile this stuff separately,
but still...

 3) Define the allocator function in a helper header in your project.
    It could be a macro like:

    #define wimp_menu_entry_new(int n) \
         g_malloc0(sizeof(wimp_menu) + \
                   (n - 1) * sizeof(wimp_menu_entry))

    The other definition would be more useful, because you wouldn't
    have to set the entries item-by-item, but also a bit more complicated.

This seems like a very good option for me. I think I'll go for this one.
Thanks!

Related: Is there documentation about this? If so where can I find
that?

Very scarce. Look through the wiki, but mostly you will have to
look how similar things are done in the existing .vapi files.

I find it very difficult to look at other .vapi files as I have almost
no experience with GLIb and other libraries, coming from RISC OS where
these libraries are not generally used, or at the very least I am not
very familiar with them. So it is difficult for me to find relevant
comparable situations and their solutions in the .vapi files.

Thanks for your help!

Cheers,
Jan-Jaap

____________________________________________________________
FREE 3D EARTH SCREENSAVER - Watch the Earth right on your desktop!
Check it out at http://www.inbox.com/earth



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