gencls --h --inc --tml -O -I<name> --depend --sayparent filename.cls
[ zero or more type declarations ] [ zero or one class declaration ]
Gencls produces .h, .inc or .tml files, with a base name of the .cls file, if no object or package name given, or with a name of the object or the package otherwise.
The types are:
int Bool Handle double SV* HV* char * string ( C declaration is char[256] )
There are also some derived built-in types, which are
long short char Color U8
that are mapped to int. The data undergo no conversion to int in transfer process, but it is stored instead to perl scalar using newSViv() function, which, in turn, may lose bits or a sign.
<scope> <prefix> <id> <definition>
A scope can be one of two pragmas, "global" or "local". They hint the usage of a new data type, whether the type will be used only for one or more objects. Usage of "local" is somewhat resembles C pragma static. Currently the only difference is that a function using a complex local type in the parameter list or as the result is not a subject for "-O" optimization.
<scope> $id => <basic_scalar_type>;
Example:
global $Handle => int;
The new type id will not be visible in C files, but the type will be substituted over all .cls files that include this definition.
<scope> id1 id2
Example:
global API_HANDLE UV
Such code creates a C macro definition in .h header file in form
#define id1 id2
C macros with parameters are not allowed. id1 and id2 are not required to be present in .cls name space, and no substitution during .cls file processing is made. This pragma usage is very limited.
Gencls allows several combinations of complex data types that C language does not recognize. These will be described below.
Complex data types do not get imported into perl code. A perl programmer must conform to the data type used when passing parameters to a function.
<scope> @id <basic_scalar_type>[dimension];
Example:
global @FillPattern U8[8];
Example of functions using arrays:
Array * func( Array a1, Array * a2);
Perl code:
@ret = func( @array1, @array2);
Note that array references are not used, and the number of items in all array parameters must be exactly as the dimensions of the arrays.
Note: the following declaration will not compile with C compiler, as C cannot return arrays. However it is not treated as an error by gencls:
Array func();
<scope> @id {
<basic_scalar_type> <id>;
...
<basic_scalar_type> <id>;
};
Example:
global @Struc {
int number;
string id;
}
Example of functions using structs:
Struc * func1( Struc a1, Struc * a2); Struc func2( Struc a1, Struc * a2);
Perl code:
@ret = func1( @struc1, @struc2); @ret = func2( @struc1, @struc2);
Note that array references are not used, and both number and order of items in all array parameters must be set exactly as dimensions and order of the structs. Struct field names are not used in perl code as well.
<scope> %id {
<basic_scalar_type> <id>;
...
<basic_scalar_type> <id>;
};
Example:
global %Hash {
int number;
string id;
}
Example of functions using hashes:
Hash * func1( Hash a1, Hash * a2); Hash func2( Hash a1, Hash * a2);
Perl code:
%ret = %{func1( \%hash1, \%hash2)};
%ret = %{func2( \%hash1, \%hash2)};
Note that only hash references are used and returned. When a hash is passed from perl code it might have some or all fields unset. The C structure is filled and passed to a C function, and the fields that were unset are assigned to a corresponding C_TYPE_UNDEF value, where TYPE is one of NUMERIC, STRING and POINTER literals.
Back conversion does not count on these values and always returns all hash keys with a corresponding pair.
<namespace> <ID> {
<declaration>
...
<declaration>
}
A .cls file can have zero or one namespace sections, filled with function descriptions. Functions described here will be exported to the given ID during initialization code. A namespace can be either "object" or "package".
The package namespace syntax allows only declaration of functions inside a "package" block.
package <Package ID> {
<function description>
...
}
The object namespace syntax includes variables and properties as well as functions ( called methods in the object syntax ). The general object namespace syntax is
object <Class ID> [(Parent class ID)] {
<variables>
<methods>
<properties>
}
Within an object namespace the inheritance syntax can be used:
object <Class ID> ( <Parent class ID>) { ... }
or a bare root object description ( with no ancestor )
object <Class ID> { ... }
for the object class declaration.
[<prefix>] <type> <function_name> (<parameter list>) [ => <alias>];
Examples:
int package_func1( int a, int b = 1) => c_func_2;
Point package_func2( Struc * x, ...);
method void object_func3( HV * profile);
A prefix is used with object functions ( methods ) only. More on the prefix in Methods section.
A function can return nothing ( void ), a scalar ( int, string, etc ) or a complex ( array, hash ) type. It can as well accept scalar and complex parameters, with type conversion that corresponds to the rules described above in ``Basic scalar data types'' section.
If a function has parameters and/or result of a type that cannot be converted automatically between C and perl, it gets declared but not exposed to perl namespace. The corresponding warning is issued. It is not possible using gencls syntax to declare a function with custom parameters or result data. For such a purpose the explicit C declaration of code along with "newXS" call must be made.
Example: ellipsis (...) cannot be converted by gencls, however it is a legal C construction.
Point package_func2( Struc * x, ...);
The function syntax has several convenience additions:
void func( int a = 15);
A function declared in such way can be called both with 0 or 1 parameters. If it is called with 0 parameters, an integer value of 15 will be automatically used. The syntax allows default parameters for types int, pointer and string and their scalar aliases.
Default parameters can be as many as possible, but they have to be in the end of the function parameter list. Declaration "func( int a = 1, int b)" is incorrect.
Example:
package Package {
void func( int x) => internal;
}
A function declared in that way will not call Package_func() C function, but internal() function instead. The only request is that internal() function must have identical parameter and result declaration to a func().
This declaration is used heavily in constructors, which perl code is typical
sub init
{
my %ret = shift-> SUPER::init( @_);
...
return %ret;
}
and C code is usually
void Obj_init ( HV * profile) {
inherited init( profile);
... [ modify profile content ] ...
}
method void a( int x)
for an object class Object is reflected in C as
void Object_a( Handle self, int x)
function declaration. Contrary to package functions, that gencls is unable to publish if it is unable to deal with the unsupported on unconvertible parameters, there is a way to issue such a declaration with a method. The primary use for that is the method name gets reserved in the object's VMT.
Methods are accessible in C code by the direct name dereferencing of a "Handle self" as a corresponding structure:
((( PSampleObject) self)-> self)-> sample_method( self, ...);
A method can have one of six prefixes that govern C code generation:
method void a()
results in
void Object_a( Handle self)
C declaration. A published method automatically converts its parameters and a result between C and perl.
Class::Object-> static_method();
its first parameter is not a object but a ``Class::Object'' string. If a method never deals with an object, it is enough to use its declaration as
static a( char * className = "");
but is if does, a
static a( SV * class_or_object = nil);
declaration is needed. In latter case C code itself has to determine what exactly has been passed, if ever. Note the default parameter here: a "static" method is usually legible to call as
Class::Object::static_method();
where no parameters are passed to it. Without the default parameter such a call generates an 'insufficient parameters passed' runtime error.
NB: methods that have result and/or parameters data types that can not be converted automatically, change their prefix to "c_only". Probably this is the wrong behavior, and such condition have to signal an error.
Properties can operate with different, but fixed amount of parameters, and perform a 'set' and 'get' functions only for one. By default the only parameter is the implicit "Handle self":
property char * name
has C counterpart
char * Object_name( Handle self, Bool set, char * name)
Depending on a mode, "Bool set" is either "true" or "false". In 'set' mode a C code result is discarded, in 'get' mode the parameter value is undefined.
The syntax for multi-parameter property is
property long pixel( int x, int y);
and C code
long Object_pixel( Handle self, Bool set, int x, int y, long pixel)
Note that in the multi-parameter case the parameters declared after property name are always initialized, in both 'set' and 'get' modes.
object SampleObject {
int x;
List list;
struct { int x } s; # illegal declaration
}
Variables are accessible in C code by direct name dereferencing of a "Handle self" as a corresponding structure:
(( PSampleObject) self)-> x;