[Vala] Binding strange APIs



I've been working on some bindings to APIs that don't always fit the
GLib/GObject style, and was thinking about a fairly easy way to handle
them. My idea is basically to use the cname, free_function,
copy_function, etc., to give people a bit more flexibility.

Everything could still work the way it is, but you could optionally add
parenthesis and specify more information about the arguments. It would
probably be easier to just give an example, so I'll use GString's free
function (which currently has special support in valac to add a second
argument):


[CCode (free_function = "g_string_free(this, TRUE)", type_id =
"G_TYPE_GSTRING")]
class String : Boxed {}


I'm currently working on bindings for gcrypt. Here is a bit of the API
that is causing problems:


struct gcry_cipher_handle;
typedef struct gcry_cipher_handle *gcry_cipher_hd_t;
gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *handle,
                              int algo, int mode, unsigned int flags);
void gcry_cipher_close (gcry_cipher_hd_t h);


Everything is based on around gcry_cipher_hd_t/(struct
gcry_cipher_handle *). Here is how I currently have my bindings setup:


[CCode (cname = "struct gcry_cipher_handle", free_function =
"gcry_cipher_close", cprefix = "gcry_cipher_")]
public class Cipher {
  public static Error open (out Cipher handle, CipherAlgos algo,
CipherModes mode, CipherFlags flags);
}


Which means I initialize my Cipher object like this:


Cipher gcry;
Cipher.open(out gcry, CipherAlgos.AES256, CipherModes.ECB,
CipherFlags.SECURE);


Obviously, a bit ugly. But if my binding could change to:


[CCode (cname = "struct gcry_cipher_handle", free_function =
"gcry_cipher_close", cprefix = "gcry_cipher_")]
public class Cipher {
  [CCode (cname = gcry_cipher_open(&this, algo, mode, flags))]
  public static Error open (CipherAlgos algo, CipherModes mode,
CipherFlags flags);
}


I can use the slightly more natural


var gcry = new Cipher();
gcry.open(CipherAlgos.AES256, CipherModes.ECB, CipherFlags.SECURE);


Another problem I've run into a lot is where a function takes an array
and length, but in that order. In vala, the only way I've found to deal
with that is to use NoArrayLength and have the user manually pass the
length. That could be changed to (still in the Cipher class):


[CCode (cname = "encrypt(outbuf, outbuf_len, inbuf, inbuf_len)")]
public Error encrypt (uchar[] outbuf, uchar[] inbuf);


From:


[NoArrayLength]
public Error encrypt (uchar[] outbuf, uint outbuf_len, uchar[] inbuf,
uint inbuf_len);


This could also be used to help with functions which accept a pre-sized
array and a pointer to an int that is then populated with the number of
characters written (http://tinyurl.com/3y69a6 comes to mind because I've
been having to use it recently).

The rules would be pretty simple. The names of arguments are re-used, as
well as *_len for the length of arrays. `this' is reserved for referring
to this, which I don't see being a problem. Beyond those simple
substitutions, the function is just output as specified, so you can add
parameters that don't appear in the vala function.

Is this at all feasible?


-Evan Nemerson




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