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
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
andext
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
andext
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 useIsa(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. TheInclude
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.