Thoughts on a Ctypes::Type object API

doubi on 2010-07-20T18:04:33

For the past few days I've been considering and experimenting with the design of simple Ctypes::Type objects. These are objects which, funnily enough, represent C data types for manipulation in Perl.

The reference implementation

Looking at the Python ctypes module, there were various things I didn't like. Python's simple types [0] can be summarized thusly:

>>> i = c_int(42)
>>> print i
c_long(42)
>>> print i.value
42
>>> i.value = -99
>>> print i.value
-99
>>>

Having to specify i.value seemed cumbersome for an object which essentially represents just that value and some rules for what kinds of values it can contain. So I started trying various things with tie'ing and overloading. Indeed, I was about to start a fourth project branch on types [1] before reigning in and having another think about fundamental behaviour.



Metaphor clash

The 'Metaphor Clash' section [2] of perldoc overload made clear the difficulty I was having with my thinking. If you want to be able to say simply,

$int_obj = 42;        # assign new value to Ctypes::Type::c_int object

and not have $int_obj smushed and replaced by a simple IV, you're forced to do something like,

$other_obj = $int_obj->copy();

on those occasions when that's the outcome you really want. That might not be regular for objects in Perl, but I think that this is more suitable in this domain, where as I mentioned before, objects are just there to represent special kinds of values. Particularly, it would let you do this:

$c_int = $c_long;        # Put long value into integer type, with
                         # appropriate checking on STORE

rather than having to say

$c_int->val = $c_long->val;

Normal usage

I think that once you've instantiated a Ctypes::Type object, what you're going to be doing 90% of the time is assigning values to it or assigning its value to other things. The times when you want to squash the object with a different object or value, instead of just creating a new one, will be rare, and there can be special methods for doing those things.

What do you think? Is this a reasonable generalisation to make? How would you like Type objects to work?

Other issues

There are a couple of other issues tangential to this which I'd like to flag up while we're at it...

  • The latter behaviour, while IMO preferable, will I think be harder to implement. I haven't yet found a way using only Perl to hide the process of tie'ing a variable from the user. This is horrible:

    my $int = 5;    # regular scalar
    c_int(\$int);    # make it a Ctypes::Type
    

    but it's one of the only ways to enable the assignment of new values to the object without using an accessor every time (the other way is returning a reference from c_int() and requiring users to say $$int all the time). I think the desired effect would be possible, but c_int() will have to be written in XS. That's fine, but I want to sound out opinions on whether I'm making the right choices on functionality first.
  • The latter behaviour, while IMO better than that in Python's ctypes, may represent a significant difference from the de facto 'conventional' way of doing things. This raises a bunch of issues to be addressed in a subsequent post.

Please do let me know what you think of the above proposals. I'm highly suggestible.


[0] http://docs.python.org/library/ctypes.html#fundamental-data-types
[1] http://gitorious.org/perl-ctypes/perl-ctypes
[2] http://perldoc.perl.org/overload.html#Metaphor-clash