NAME

Class::CompiledC

VERSION

This document describes version 2.21 of Class::CompiledC, released Fri Oct 27 23:28:06 CEST 2006 @936 /Internet Time/

ABSTRACT

Class::CompiledC -- use C structs for your objects.

SYNOPSIS

package Foo;
use strict;
use warnings;

use base qw/Class::CompiledC/;

sub type     : Field(String);
sub data     : Field(Hashref);
sub count    : Field(Int);
sub callback : Field(Coderef);
sub size     : Field(Float);
sub dontcare : Field(Number);
sub dumper   : Field(Isa(Data::Dumper));
sub items    : Field(Arrayref);
sub notsure  : Field(Object);

my $x;

$x = Foo->new(-type     => "example",
              -data     => {},
              -count    => 0,
              -callback => sub { print "j p " ^ " a h " ^ " " x 4 while 1},
              -size     => 138.4,
              -dontcare => 12,
              -dumper   => Data::Dumper->new,
              -items    => [qw/coffee cigarettes beer/],
              -notsure  => SomeClass->new
              );

DESCRIPTION

Note: Documentation is incomplete, partly outdated, of poor style and full of typos. I need a ghostwriter.

Class::CompiledC creates classes which are based on C structs, it does this by generating C code and compiling the code when your module is compiled (1). You can add constraints on the type of the data that can be stored in the instance variables of your objects by specifiying a field type (i call instance variables fields because it's shorter). A field without constraints are declared by using the : Field attribute (2) on a subroutine stub (3) of the name you would like to have for your field eg. sub Foo : Field; this would generate a field called 'foo' and it's accesor method, also called 'foo' If you want to add a constraint to the field just name the type as a parameter for the attribute eg sub foo : Field(Ref).

(1) (actually, Class::CompiledC utilizes Inline to do the dirty work; Inline uses Inline::C to do it's job and Inline::C employes your C compiler to compile the code. This means you need Inline Inline::C and a working C compiler on the runtime machine.

(2) attributes perl6 calls them traits or properties; see attributes not to confuse with instance variables (fields) which are sometimes also called attributes; terms differ from language to language and perlmodules use all of them with different meanings, very confusing

(3) sub foo; remember ? also called forward declaration see perlsub

for the truly insane.

TODO

Supported Field Types

The following Field types are currently supported by Class::CompiledC

Any

sub Foo : Field(Any)

NOOP. Does nothing, is even optimized away at compile time. You can use it to explicitly declare that you don't care.

Arrayref

sub Foo : Field(Arrayref)

Ensures that the field can only hold a reference to an array. (beside the always legal undefined value).

Coderef

sub Foo : Field(Coderef)

Ensures that the field can only hold a reference to some kind of subroutine. (beside the always legal undefined value).

Float

sub Foo : Field(Float)

Ensures that the field can only hold a valid floating point value. (An int is also a valid floating point value, as is undef).

Hashref

sub Foo : Field(Hashref)

Ensures that the field can only hold a reference to a hash. (beside the always legal undefined value).

Int

sub Foo : Field(Int)

Ensures that the field can only hold a valid integer value. (beside the always legal undefined value).

Isa

sub Foo : Field(Isa(Some::Class))

Ensures that the field can only hold a reference to a object of the specified class, or a subclass of it. (beside the always legal undefined value). (The relationship is determined the same way as the UNIVERSAL-isa> method)

Number

sub Foo : Field(Number)

At current this just an alias for the Float type, but that may change.

Object

sub Foo : Field(Object)

Ensures that the field can only hold a reference to a object. (beside the always legal undefined value).

Ref

sub Foo : Field(Ref)

Ensures that the field can only hold a reference to something. (beside the always legal undefined value).

Regexpref

sub Foo : Field(Regexpref)

Ensures that the field can only hold a reference to a regular expression object. (beside the always legal undefined value).

String

sub Foo : Field(String)

Ensures that the field can only hold a string value. Even everything could theoretically expressed as a string, only true string values are legal. (beside the always legal undefined value).

Field Types Specification Syntax Note

Field types are case insensitve. If a type expects a parameter, as the Isa type, then it should be enclosed in parenthises. Whitespace is always ingnored, around Field types and parameters, if any. Note, however that the field type Int, spelled in lowercase letters will be misparsed as the `int` operator, so be careful.

Additional Features

Currently there are two categories of additional features: those going to stay, and those going to be relocated into distinct packages.

First the stuff that will stay:

parseArgs method

Every subclass inherits this method. Its purpose is to ease the use of named parameters in constructors. It takes a list of key => value pairs. Foreach pair it calls a method named like the key with value as it only parameter (beside the object, of course), i.e:

$obj->parseArgs(foo => [], bar => 'bar is better than foo');

Would result in the following method calls:

$obj->foo([]);
$obj->bar('bar is better than foo');

The method also strips a leading dash ('-') from the method name, in case you prefer named arguments starting with a dash, therefore the following calls are equivalent :

$obj->parseArgs(-foo => 123, -bar => 456); # dashed style

$obj->parseArgs(foo => 123, bar => 456);   # dashless style

$obj->parseArgs(-foo => 123, bar => 456);  # no style

Since this method needs key => value pairs it will croak if you supply it an odd number of arguments. actually it croaks on an even number of arguments, if you also count the object. but the check for oddnes is done after the object is shifted from the argument list

parseArgs returns the object.

new method

Every subclass inherits this method, it is merely a wrapper around the real constructor (which is called 'create'). It first constructs the object (with the help of the real constructor) and then calls parseArgs on it. This means the following code is equivalent :

my $obj = class->new(-foo => 'bar');

#----

my $obj = class->create;
$obj->parseArgs(-foo => 'bar');

Only shorter ;)

inspect method

This method is created for each subclass. It returns a hashref with the field names and their types. A short example should clarify what I try to say:

package SomeClass;
use base qw/Class::CompiledC/;

sub foo : Field(Int);
sub bar : Filed(Hashref);

#### at same time in some other package:

use SomeClass;
use Data::Dumper;

my $obj = Somelass->new;

print Dumper($obj->inspect);

### prints something like

$VAR1 = {
              'foo' => 'Int',
              'bar' => 'Hashref',
        }

Be aware that this purely informational. Even you can change the data behind this reference, nothing will happen. The changes will not persist, if you call inspect again, the output will be the same. Especially do not expect that you can change a class on the fly with that hash, this won't work. You should also know that two calls to inspect will result in two distinct hash references, so don't try to compare those references. Even the hash those references refer to is diffrent, if you really want to compare than you have to do a deep compare.

the C attribute

The C attribute allows you to write a subroutine in C, eg:

sub add : C(int, int a, int b)
{q{
      return a + b;
}}

The return type and the parameters are specified in the attribute, and the function body is in the subroutine body. Therefore the resulting C code looks like:

int add(int a, int b)
{
        return a + b;
}

You may have noticed that the actual body of the C function is whatever the (Perl subroutine returned, so this code :

sub getCompileTime(int, )
{
        my $time = time;
        my $code = "return $time";

        return $code;
}

will result in this C code :

int getCompileTime()
{
        return 1162140297;
}

The time value, is subject of change, of course. If you wonder what perl can do with c intergers, all (with a few exceptions) C code is subject to XS-fication by the "Inline::C module", which handles this sort of crap behind the scenes. You should have a look at Inline::C for bugs and deficiencies, but do yourself and the author of Inline a favor and not report any bugs that might showup in conjunction with Class::CompiledC to the author of Inline, report them to me. I'm cheating with Inline, and most problems you might encounter wouldn't show up by using Inline correctly.

Be advised that you have full access to perls internals within your C code and to take any usage out of this feature you should read the following documents:

perlxstut

Perl XS tutorial

perlxs

Perl XS application programming interface

perlclib

Internal replacements for standard C library functions

perlguts

Perl internal functions for those doing extensions

perlcall

Perl calling conventions from C

XXX The stuff that will be outsourced is not yet documented.

Of course, you should also know how to code in C. One final notice: This feature has been proven as an endless source of fun and coredumps.

Methods

The methods listed here are not considered part of the public api, and should not be used in any way, unless you know better.

Class::CompiledC defines the following methods:

__scheduled

__scheduled SELF, PACKAGE
Type: class method

the __scheduled method checks if package has already been scheduled for compilation. returns a a true value if so, a false value otherwise.

__schedule

__scheduled SELF, PACKAGE
Type: class method

the __schedule method schedules PACKAGE for compilation. Note.: try not to schedule a package for compilation more than once, you can test for a package beeing scheduled with the __scheduled method, or you can use the __scheduleIfNeeded which ensures that a package doesn't get scheduled multiple times.

__scheduleIfNeeded

__scheduleIfNeeded SELF, PACKAGE
Type: class method

the __scheduleIfNeeded method schedules PACKAGE for compilation unless it already has been scheduled. Uses __scheduled to determine 'scheduledness' and __schedule to do the hard work.

__addCode

__addCode SELF, PACKAGE, CODE, TYPE
Type: class method

Add code CODE for compilation of type TYPE to PACKAGE. Currently supported types are base (code for fields) and ext (code for addional c functions). Before compilation base and ext coe is merged, base first, so that ext code can access functions and macros from the base code.

__compile

__compile SELF, PACKAGE
Type: class method

Compiles the code for PACKAGE.

__traverseISA

__traverseISA SELF, PACKAGE, HASHREF, [CODEREF]
Type: class method

Recursivly traverses the @ISA array of PACKAGE, and returns a list of fields declared in the inheritance tree of PACKAGE. HASHREF which must be supplied (and will be modified) is used to ensure that fields will only show up once. CODEREF is a optional parameter, which, when supplied,must be a reference to the method itself and is used for recursion. If CODEREF is not supplied, __traverseISA determines it on it's own.

__addParentFields

__addParentFields SELF, PACKAGE
Type: class method

Adds the fields from SUPER classes to the list of fields.

__doIt

__doIt SELF, PACKAGE
Type: class method

Inherits parents fields, generates base code, generates ext code, and starts compilation for package PACKAGE. This method is meant to be called from CHECK block in the target package. The __schedule or more safely the __scheduleIfNeeded method can arrange that for you.

__genExtFuncCode

__genExtFuncCode SELF, PACKAGE, NAME, RETVAL, ARGS, CODEREF
Type: class method

Generates a single ext function, NAME in package PACKAGE with return type RETVAL and parameters ARGS, with the body returned from CODEREF. Meant to be called by the __genExtCode method.

__genExtCode

__genExtCode SELF, PACKAGE
Type: class method

Generates all ext functions in package PACKAGE. Utilizes the __genExtFuncCode method to do the dirty work. You can define ext functions with the C attribute.

__genBaseCode

__genBaseCode SELF, PACKAGE
Type: class method

Generates the C code for all fields. You can define fields with the Field attribute.

parseArgs

parseArgs SELF, LOTS_OF_STUFF
Type: object method

Used for named parameters in constructors. Returns the object, for simplified use in constructors.

new

new SELF, PACKAGE, LOTS_OF_STUFF
Type: class method

Highlevel Constructor, first calls the create constructor to allocate the C structure, and then calls parseArgs to initialize the object.

Subroutines

The subroutines listed here are not considered part of the public api, and should not be used in any way, unless you know better.

Class::CompiledC defines the following subroutines

__circumPrint

__circumPrint TEXT, LEFT, RIGHT
Type: Subroutine.
Export: on request.
Prototype: $$$

Utitlity function, concatenates it's arguments, in the order $_[1].$_[0].$_[1] and returns the resulting string. Does not print anything.

__include

__include I<NOTHING>
Type: Subroutine.
Export: on request.
Prototype: none

Takes $_ and returns a string in form \n#include $_\n. This subroutine is used to generate C include directives, from the Include attribute. Note that it doesn't add <> or "" around the include, you have to do this your self.

__baseref

__baseref REFERENCE, TYPE
Type: Subroutine.
Export: on request.
Prototype: $$

Determines if REFERENCE is actually a reference and and is of type TYPE.

__hashref

__hashref REFERENCE
Type: Subroutine.
Export: on request.
Prototype: $

Determines if REFERENCE is actually a hash reference. Utitlizes __baseref.

__arrayref

__arrayref REFERENCE
Type: Subroutine.
Export: on request.
Prototype: $

Determines if REFERENCE is actually a array reference. Utitlizes __baseref.

__coderef

__coderef REFERENCE
Type: Subroutine.
Export: on request.
Prototype: $

Determines if REFERENCE is actually a code reference. Utitlizes __baseref.

__fetchSymbolName

__fetchSymbolName GLOBREF
Type: Subroutine.
Export: on request.
Prototype: $

Returns the Symbol name from the glob reference GLOBREF. Croaks if GLOBREF acutally isn't a glob reference.

__promoteFieldTypeToMacro

__promoteFieldTypeToMacro FIELDTYPE
Type: Subroutine.
Export: on request.
Prototype: none

Takes a fieldtype specfication, and returns a C macro for doing the test. Does not handle parametric types like isa. See __parseFieldType for that.

__parseFieldType

__parseFieldType FIELDTYPE
Type: Subroutine.
Export: on request.
Prototype: none

Takes a fieldtype specfication, and returns a C macro for doing the test. Handles all field types. Delegates most work to the __promoteFieldTypeToMacro subroutine.

Include

sub Foo : C(...)     Include(<math.h>)
sub Foo : Field(...) Include("bar.h")

Type: Attribute Handler
Export: no.

C

sub Foo : C(RETVAL, ARG0, ...)

Type: Attribute Handler
Export: no.

Field

sub Foo : Field(TYPE)

Type: Attribute Handler
Export: no.

Alias

sub Foo : Alias(\&REALMETHOD)

Type: Attribute Handler
Export: no.

Overload

sub Foo : Overload(OPERATOR)

Type: Attribute Handler
Export: no.

Const

sub Foo : Const(VALUE)

Type: Attribute Handler
Export: no.

Abstract

sub Foo : Abstract

Type: Attribute Handler
Export: no.

Class

sub Foo : Class(CLASS)

Type: Attribute Handler
Export: no.

Inheritance

Class::CompiledC inherits the following methods from it's ancestors

methods inherited from Attribute::Handlers
import
_resolve_lastattr
DESTROY
_gen_handler_AH_
_apply_handler_AH_

Export

Class::CompiledC does not export anything by default but has a number of subroutines to Export on request.

Export Tags

Class::CompiledC defines the following export tags:

ref Subroutines to verify the type of references
misc miscellanous subroutines
field specification subroutines
intern miscellanous subroutines with low value outside this package
all Everything.

Exportable Symbols

The following subroutines are (im|ex)portable, either explicitly by name or as part of a tag.

__include
__arrayref
__coderef
__hashref
__fetchSymbolName
__baseref
__circumPrint
__parseFieldType
__promoteFieldTypeToMacro

EXAMPLES

TODO

DIAGNOSTICS

no package supplied

this message is usually caused by an class method called as a subroutine. fatal error

no target package supplied

Some methods (and subroutines, btw) need a target package to operate on, it seems that the argument is missing, or has evaluated to false value, which very unlikely to be valid. fatal error

no code supplied

This message is is caused by the __addCode method, which renders useless without a supplied code argument. fatal error

no type supplied

This message is caused by the __addCode method, when called without a type argument. The __addCode method can only operate with a valid type argument. Currently valid types are base and ext but more may be added in future. fatal error

bad type supplied

This message is caused by the __addCode method, when called with a invalid type argument. Currently valid types are base and ext but more may be added in future. fatal error

fail0r: isa type needs a classname argument

This message is caused by the __parseFieldType subroutine. The __parseFieldType subroutine (which gets called by the Field attribute handler) found isa as type but without a classname. A is a check doesn't make sense without a classname. If you just want to make sure that it is a object, you may use Isa(Universal) or (generally faster and shorter) Object. fatal error

fail0r: not a hash reference

This message is caused by the __traverseISA method, which needs a hashreference as third argument, for speed considerartions. fatal error

fail0r: f arg supplied but not a code ref

This message is caused by the __traverseISA method, which accepts a reference to itself, both for efficiency reasons and security from renamings. fatal error

no found hash supplied

This message is caused by the __traverseISA method, when called without the third argument. (Which must be a hashreference, and will be changed by the method) fatal error

no symbol supplied

This message can be issued from different sources, but most often by attribute handlers, which misses a reference to a typeglob. Don't call attribute handlers on your own. (unless you really know what you do) fatal error

no reference supplied

This message can be issued from different sources, but most often by attribute handlers, which misses a reference to whatever they decorate. Don't call a ttribute handlers on your own. (unless you really know what you do) fatal error

no attribute supplied

This message can be issued from different sources, but most often by attribute handlers, which misses the attribute they should handler. Don't call a ttribute handlers on your own. (unless you really know what you do) fatal error

no includes supplied

This message is caused by the Include attribute handler. The Include handlers just couldn't figure out what to do. Give him a hand and specify what should be included. fatal error

no return type and parameters specified

This message is specific to the C attribute handler subroutine. To compile the code it needs to know the return type and the parameter list of the C function to be compiled. fatal error

no name supplied

This message is caused by the __genExtFuncCode method when called without a fieldname. fatal error

no retval supplied

This message is caused by the __genExtFuncCode method when called without a return type argument. fatal error

no args supplied

This message is caused by the __genExtFuncCode method when called without a args argument. fatal error

BUGS

There are undoubtedly serious bugs lurking somewhere.

there is a (undocumented) UINT type specifier for unsigned ints, but it doesn't work right, actually it doesn't work at all, don't try to use it.

TODO

*serious code cleanup

I still find too much things that are done the fast way instead of the right way, this really bothers me.

*outsourcing

A few things need to be outsourced right away. I just don't know where to put them. Especially the stuff not related to classes should be placed somewhere else. The utility __.* subs (not methods!) could be placed in a different package and locally (or maybe lexically?) imported, to avoid namespace pollution of subclasses.

Random thought: lexical importing ? what a cute idea! is this possible?

SEE ALSO

TODO

AUTHOR

blackhat.blade The Hive

blade@focusline.de

COPYRIGHT

                   Copyright (c) 2005, 2006
       blackhat.blade The Hive.  All Rights Reserved.
This module is free software. It may be used, redistributed
    and/or modified under the terms of the Artistic license.