NAME

Code::Class::C - Perl extension for creating ANSI C code from a set of class definitions to accomplish an object-oriented programming style.

SYNOPSIS

use Code::Class::C;
my $gen = Code::Class::C->new();

$gen->class('Shape',
  subs => {
    'getLargest(s:Shape):Shape' => 'c/Shape.getLargest.c',
    'calcArea():float' => q{
      return 0.0;
    },
  },
);

$gen->class('Circle',
  isa => ['Shape'],
  attr => {
    'radius' => 'float',
  },
  subs => {
    'calcArea():float' => q{
      return 3.1415 * getRadius(self) * getRadius(self);
    },
  },
);

DESCRIPTION

This module lets you define a set of classes (consisting of attributes and methods) and then convert these definitions to ANSI C code. The module creates all the object oriented abstractions so that the application logic can be programmed in an object oriented fashion (create instances of classes, access attributes, destroy instances, method dispatch etc.).

Constructor

new()

my $gen = Code::Class::C->new();

The constructor of Code::Class::C takes no arguments and returns a new generator instance with the following methods.

Methods

class( name, options )

The class() method lets you define a new class:

$gen->class('Circle',
  isa => ['Shape'],
  attr => {
    'radius' => 'float',
  },
  subs => {
    'calcArea():float' => q{
      return 3.1415 * getRadius(self) * getRadius(self);
    },
  },
);

The class() method takes as first argument the name of the class. The name has to start with a capitol letter and may be followed by an arbitrary amount of letters, numbers or underscore (to be compatible with the ANSI C standard).

The special class name Object is not allowed as a classname. A classname must not be longer than 256 characters.

After the first argument the optional parameters follow in any order:

isa => Arrayref of classnames

The isa option lets you specify zero or more parent classes of the class that is to be defined.

attr => Hashref of attributes

The attr option lets you define the attributes of the class that is to be defined.

The hash key is the name of the attribute (starting with a small letter and followed by zero or more letters, numbers or underscore; note: attribute names are case-insensitive).

The hash value is the C-type of the attribute. Here you can use basic C types OR class names (because each class becomes available as a native C type when the C code is generated).

subs => Hashref of methods

The subs option lets you define the methods of the class that is to be defined.

The hash key is the signature of the method, e.g.

calcArea(float x, MyClass y):int

The hash value is the C sourcecode of the method (s.b. for details). The hash value can optionally be a filename. In this case, the file's content is used as the method's body.

attr( classname, attribute-name, attribute-type )

Defines an attribute in a class with the given name and type.

$gen->attr('Shape','width','float');

meth( classname, method-signature, c-code )

Defines a method in a class of the given signature using the given piece of C code (or filename).

$gen->meth('Shape','calcArea():float','...');

parent( classname, parent-classname, ... )

Defines the parent class(es) of a given class.

$gen->parent('Shape','BaseClass1','BaseClass2');

readFile( filename )

readFile() takes one argument, a filename, loads this file and extracts class, attribute and method definitions from it.

$gen->readFile('c/Triangle.c');

Here is an example file:

//------------------------------------------------------------------------------
@class Triangle: Shape, Rectangle

//------------------------------------------------------------------------------
@attr prop:int

//------------------------------------------------------------------------------
// calculates the area of the triangle
//
@sub calcArea():float

return self->width * self->height;

//------------------------------------------------------------------------------
// calculates the length of the outline of the triangle
//
@sub calcOutline():float

return getWidth(self) * 2 + getHeight(self) * 2;

A line starting with '//' is ignored. A line that starts with an '@' is treated as a class or attribute definition line or as the start of a method definition. I hope this is self-explanatory?

Such files can be saved with an ".c" extension so that you can open them in your favourite C code editor and have fun with the highlighting.

func( signature, c-code-or-filename )

The func() method defines a normal C function. It takes as parameters the signature of the function and the code (which can be a code string or a filename):

$gen->func('doth(float f, Shape s):int', '/* do sth... */');

generate( options )

$gen->generate(
  file    => './main.c',
  headers => ['stdio','opengl'],
  main    => 'c/main.c',
  top     => 'c/top.c',
  bottom  => 'c/bottom.c',
);

The generate() method generates a single ANSI C compliant source file out of the given class definitions.

The options are:

file => filename

This defines the name of the C output file. This option is mandatory.

headers => Arrayref of headernames

This defines C headers that are to be included in the generated C file.

main => Source or filename of main function body

This defines the body (C code) of the main function of the generated C file. This can be either C code given as a string OR a filename which is loaded.

top => Source or filename of C code

This method adds arbitrary C code to the generated C file. The code is added after the class structs/typedefs and before the method (function) declarations.

bottom => Source or filename of C code

This method adds arbitrary C code to the generated C file. The code is added to the end of the file, but before the main function.

toDot()

This method generates a Graphviz *.dot string out of the class hierarchy and additional information (attributes, methods). The dot string is returned.

toHtml()

This method creates a HTML API documentation to the class hierarchy that is defined. The HTML string is returned.

Object oriented features & C programming style

Throughout this document the style of programming that module lets the programmer use, is called object oriented, but this is just the canonical name, actually it is class oriented programming.

So you have defined a bunch of classes with attributes and methods. But how do you program the method logic in C? This module promises to make it possible to do this in an object-oriented fashion, so this is the section where this fashion is described.

For a more complete example, see the t/ directory in the module dictribution.

Class definition

This module lets you define classes and their methods and attributes. Class definition is not possible from within the C code.

Instanciation

Arbitrary instances of classes can be created from within the C code.

Suppose you defined a class named 'Circle'. You can then create an instance of that class like so (C code):

Object c = new_Circle();

Important: All class instances in C are of the type "Object"!

Instance destruction

Since there is a way to create instances, there is also a way to destroy them (free the memory they occupy).

A generic C function delete() is generated which can be used to destruct any object/instance:

Object c = new_Circle();
delete(c); // c now points to NULL

Inheritance

A class inherits all attributes and methods from its parent class or classes. So multiple inheritance (multiple parent classes) is allowed.

Attribute access

Suppose you defined a class named 'Circle' with an attribute (could also be inherited). Then you can access this attribute the following:

float r;
Object c = new_Circle();
r = getRadius(c);

setRadius(c, 42.0);

As you can see, all methods (either getter or setter or other ones) need to get the object/instance as first parameter. This "self" parameter need not be written when defining the method, remember to define a method, only the addtional parameters are to be written:

calcArea(int param):float

Remember: Always access the instance/object attributes via the getter or setter methods!.

Attribute overloading

Attributes once defined, must not be re-defined by child classes.

Method invocation

To invoke a method on an object/instance:

Object c = new_Circle();
printf("area = %f\n", calcArea(c));

The first argument of the method call is the object/instance the method is invoked on.

Method overloading

Methods once defined, can be overloaded by methods of the same class. Methods in a class can also be re-defined by child classes.

If a child class overwrites the method of one of its parent classes, the signatures must be the same, regarding the non-class typed parameters.

To illustrate this, here is an example of a parent class method signature: doSth(Shape s, float f):void - the first parameter is an object of class 'Shape', the second a native C float.

Suppose another classes tries to overwrite this method. In this case the first parameter's type is allowed to change (to any other class type!), but the second not, because its a native type. This will work: doSth(Circle s, float f):void but this not: doSth(int s, float f):void

Access "self" from within methods

When writing methods you need access to the object instance. This variable is "magically" available and is named "self". Here is an example of a method body:

printf("radius of instance is %f\n", getRadius(self));

Default attributes

The following attributes are present in all classes. These attributes differ compared to user-defined attributes in the way that they can be accessed directly by dereferencing the instance/object pointer:

int classid

Each class has a globally unique ID, a positive number greater than zero.

Object c = new_Circle();
printf("c.classid = %d\n", c->classid);

char* classname

This is the name of the class of the object/instance. To access the classname, use accessor methods like for all other attributes, e.g.:

Object c = new_Circle();
printf("c.classname = %s\n", c->classname);

Beware, that, when you change the classname at runtime, methods may not be able to determine the actual implementation of a method to be applied to an object/instance.

LIMITATIONS & BUGS

This module is an early stage of development and has therefor some limitations and bugs. If you think, this module needs a certain feature, I would be glad to hear from you, also, if you find a bug, I would be glad to hear from you.

EXPORT

None by default.

SEE ALSO

Please send any hints on other modules trying to accomplish the same or a similar thing. I haven't found one, yet.

AUTHOR

Tom Kirchner, <tom@tomkirchner.com>

COPYRIGHT AND LICENSE

Copyright (C) 2011 by Tom Kirchner

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.10.0 or, at your option, any later version of Perl 5 you may have available.