Writting GNU/EDMA Components
----------------------------
Abstract
--------
In this paper we will describe the process we must follow to build GNU/EDMA components and classes which can be used latter in our applications. The whole process will be described first, and then we will introduce some graphical tools that simplify the component built process.

1. Introduction
---------------
The first thing we must know is that a GNU/EDMA class has two main parts. The first one is the so called Interface Definition File, a text file (really it can be of any form using the IngrIDF subsystem) that defines the class/component interface. The second one is the component implementation, that is the code we will run when using the component.

This is the typical approach in most OO environments (i.e. COM, XPCOM, CORBA even RPC). You write your objects interface in some interface definition language and, using a interface compiler you generate some code stuff required to build your object implementation and to use those objects from your client applications.

In GNU/EDMA this is a bit different. You must write a interface definition file using some interface definition language (one quite simple is provided), but you don't need to use a interface compiler. Actually you can do that and then generate the same code COM or CORBA uses to provide a tight programming language mapping with the object generated.

Working this way has advantages and disadvantages. The main advantage is that the code generated will be used by the compiler for early type checking, finding posible errors in the application. The disadvantage to using the interface compiler is that any change you can do in the object's interface requires to recompile a lot of things. 

Currently there isn't no interface compiler and the usual way you will be GNU/EDMA applications and components is using the system primitives, that is no interface compiler generated wrapper is used at all in this paper. We will do a brief comment about this at the end of the paper.

2. Writting the interface definition file
-----------------------------------------
The default interface definition language used by GNU/EDMA is quite simple. It just allow to define some general information as well as properties and methods. The structure is like a .ini old windows file format, divided in sections each section containing a set of fields.

Let's define a IDF file for one simple HELLO_WORLD class. It will look like this:

[General]
Name=HELLO_WORLD
[SYS_DEF]
ModuleName=HELLO_WORLD.dll
[Definition]
PropertiesNum=2
MethodsNum=3
[Prop0]
Name=num
Type=EUINT32
Access=READ/WRITE
ArrayElems=
[Prop1]
Name=str
Type=EZSTRING
Access=READ/WRITE
ArrayElems=
[Met0]
Name=born
Signature=
Virtual=0
[Met1]
Name=rip
Signature=
Virtual=0
[Met2]
Name=say
Signature=
Virtual=0
[]

There are five main section in a EDMAIDF file (that is how they are named). The first one provides general information about the component, typically it just contains the component name.

Next section, SYS_DEF, is reserved to store system dependent information. Typically it just contains the implementation module name, but it isn't really necesary.

Then follow the real component interface which has three main parts. The first one defines the elements we will find in next sections, and the two other defines, respectively, the properties and methods this component has.

The definition section has three main field. The PropertiesNum which indicates how many properties will be defined bellow in the file. The MethodNum which is the same but for the method definition, and finally the SuperClass list that we will not comment in this tutorial. It is described in detail in the GNU/EDMA Inhertiance Tutorial.

2.1 Property Definition
-----------------------
Each property is defined using four fields. First one is the property name, the string we will use with WProp3 and RProp3 primitives to refer to this property. Next we find the property type, a string that can get its value from this list:

ESint32, ESint16, ESint8	: Signed Integers
EUint32, EUint16, EUint8	: Unsigned Integers
EChar				 							: Character or Byte
EByte, EWord, EDWord			: Byte, word and dword
EReal32, EReal64					: float and double
EZString									: Zero terminated string
EBuffer										: EDMAT_BUFFER data
EOBject										: A Generic GNU/EDMA Object

FIXME: Check if some is missing.

The next field required to define a property is the Access field. This field allows to set access modifiers for the property being defined. The permited values are: READ, WRITE, READ/WRITE

Finally, we can make some property a fixed array of basic types, setting the ArrayElems field.

2.2 Method Definition
---------------------
Method sections are quite similar to property ones, but using some diferent field. The first field, as in the property case is the method name.

Next field is the method signature. The signature is a character string which codes the parameter and return types for the method being defined. This field can be left blank, but it's recomended to fill in it in order to provide full reflection capabilities to the system. Not doing this will prevent the component being defined not to work properly in some cases.

Next follows the signature strings assoaciated with the basic GNU/EDMA types:

ESint32, ESint16, ESint8  : S32,S16,S8
EUint32, EUint16, EUint8  : U32,U16,U8
EChar                     : C
EByte, EWord, EDWord      : B,W,DW
EReal32, EReal64          : R32,R64
EZString                  : Z
EBuffer                   : A
EOBject                   : O

To define a parameter as an output parameter, a 's' must be prepend to the signature string (s stands for salida, the spanish word for output). The method return type is defined is specified prepending a 'r' charecter to the appropiated type signature.

Let's see some examples of valid signatures:

method (ESint32 a,ESint32 b,ESint32 *c) -> S32S32sS32
ESint32 method (EPChar name)						-> ZrS32
OBJID method(EReal64 a,EReal64 b)				-> R64R64rO

Finally, we can provide special modificator for each method being definedi, this modifiers are of type boolean being valid values 0 or 1, and all are optional. The available modifiers are:

Virtual: Defines the method as virtual what means that it can be overriden
Abstract: An abstract method is a method that don't have assoaciated implementation.
Static: Defines the method as static what means that it is related to the class not the instances of the class.

2.3 Constructors and Destructors
--------------------------------
GNU/EDMA allows to define contructor and destructor methods for the classes. This methods are the executed when class instances are created or destroyed using NewObj or FreeObj respectively.

Contructor method must be named born and destructor method must be named rip. In the current implementation it isn't possible to provide parameters to this special methods.

3. The implementation file
--------------------------
Now we know how to write our IDF's (Interface Definition Files), we must write the implementation file, the code we want our component to provide. In this tutorial we will just deal with in-process component, that is, components implemented with shared libraries. So, what we need to build is a shared library, but with an special struct.

3.1 Providing a data struct to access properties
------------------------------------------------
GNU/EDMA allocate the required memory to store the properties defined in the assoaciated IDF automatically when a class/component instance is created, and provides the primitives WProp3 and RProp3 to access them. 

However, the class implementation, normally, will often access this properties and then it must do that in a easy way. For doing that, we will define a C struct to access the properties we have defined in the IDF file and then use the GetRef primitive to map the properties values to that struct.

For our HELLO_WORLD example we should define a struct like this:

typedef struct
  {
		EUint32		num;
		EPChar		str;
}DtHELLO_WORLD;

Using this struct we can call GetRef primitive and the access the properties values through an ordinary pointer instead of the property primitives GNU/EDMA provides. Let's see how this is done:

ESint32 EDMAPROC HELLO_WORLDborn(OBJID IdObj)
{
DtHELLO_WORLD	*m;

m=(DtHELLO_WORLD*)GetRef3(IdObj);
}

As we can see GetRef3 primitive just provides a pointer to the memory address where GNU/EDMA allocated the memory chunck required to store the properties defined in the IDF file. From here we just manipulate properties using the fields in our C struct.

3.2 Writting the code
---------------------
Now we just must to write the code for our methods. For doing this we must define a function for each defined method with a special name. The name follows the next format:

CLASS_NAME|Method_Name|Signature

So, for our previous IDF file  we must define this methods

ESint32 EDMAPROC HELLO_WORLDborn(OBJID IdObj)
{
	return 0;
}

ESint32 EDMAPROC HELLO_WORLDrip(OBJID IdObj)
{
	return 0;
}

ESint32 EDMAPROC HELLO_WORLDsay(OBJID IdObj)
{
	DtHELLO_WORLD	*m;

	m=(DtHELLO_WORLD*)GetRef3(IdObj);
	printf ("Hello World! %s",m->str);
}

Note that the first parameter for each method is always a GNU/EDMA object. It is the equivalent to the this or self hidden parameter used in most of the current OO programming language. 

In this simple example no signature exists for the methods been defined and the constructor and destructor does nothing with properties. The say method will use the properties so we declare a pointer to our previously defined struct and we call GetRef3 in order to access properties values through this pointer in a efective way.

At this point we just have to write the code we want out GNU/EDMA component to run when invoking methods.

3.3 Static Methods
------------------
In the above example no static method was defined in the associated IDF, but we must to comment how to define this static methods because they differ from the showed above.

As we have said, a static method is related to a class not to an object, so, when GNU/EDMA executes the SMet3 primitive it doesn't pass as first parameter an OBJID, instead it passes a CLASSID type what is a class identifier. With this information a hello static method implementation for our GNU/EDMA component will look like this:

EVoid EDMAPROC HELLO_WORLDhello(CLASSID cid) {
	printf ("Hello World!!!\n");
}

Or with paramters:

EVoid EDMAPROC HELLO_WORLDhelloYou(CLASSID cid,EPChar name) {
  printf ("Hello %s!!!\n",name);
}

This methods can be used form your applications this way:

SMet3("HELLO_WORLD","hello");
SMet3("HELLO_WORLD","helloYou","John");

4. Building the dynamic library
-------------------------------
To generate the implementation shared library we will use a simple makefile that we show here:

CC=gcc
CFLAGS=`edma-config --cflafs-class`
LIBS=`edma-config --libs-class`
HELLO_WORLD.so: temp.o
	$(CC) -shared -Wl,-soname,libHELLO_WORLD.so.1 -o $@ temp.o $(LIBS)
temp.o: HELLO_WORLD_imp.c
	$(CC)  $(CCFLAGS) $< -o $@

As we can see it is a classical shared library make file without no more complications

5. Installing the component
---------------------------
Once we have our interface and implementation files we can install our just built GNU/EDMA component in the system and make it available to every application.

The installation consists on putting the IDF file and the shared library in place and then update the GNU/EDMA registry. In a default instalation the IDF files are stored in /usr/local/share/edma/idf and the shared libraries are saved in /usr/local/lib.

To update the GNU/EDMA registry you have two choices. The first is to manually edit the registry that, by default is located at /usr/local/etc/edma/edma32.cfg. The second is to generate a .ines file and use the class_register tool distributed with the system. Let's see how a .ines file looks like:

ClassName=HELLO_WORLD
Machine=i386
OperatingSystem=LINUX
Implementation=HELLO_WORLD.so
IDFParser=EDMAIDF

Basically a .ines file contains the same information you must add manually to the GNU/EDMA registry needed to inform GNU/EDMA about the kind of class it must deal with. In our example we will deal with a simple class, but there are some special classes that should be defined in the system registry.

To add manually a class to the system, you must first increment the value in file nClasses at the begining of the edma32.cfg file, and the add a section at the end of the file with the fields showed above when we talk about .ines file. The end of edma32.cfg after installing our HELLO_WORLD class will look like this (then numbers in [ClassXXX] will vary depending on how many classes you have installed in your system)

[General]
nClasses=28
[CLASS0]

...

[CLASS26]
ClassName=NFILE1
Machine=i386
OperatingSystem=LINUX
Implementation=libNFILE1.so
IDFParser=EDMAIDF
[CLASS27]
ClassName=HELLO_WORLD
Machine=i386
OperatingSystem=LINUX
Implementation=HELLO_WORLD.so
IDFParser=EDMAIDF

[]

6. Testing the new component
----------------------------
The first test you must to do is run the GNOME Class Browser and check the new component is correctly detected and the interface the application shows is the one you defined.

Then you can write a simple test program. Refer to Writting GNU/EDMA application tutorial to do this.

7. Writting a wrapper for our HELLO_WORLD class
-----------------------------------------------
At this point writing a wrapper for a GNU/EDMA component should be a trivial task you simple need to write functions invoking the Met3 primitive. Let's see a minimal example:

typedef OBJID HELLO_WORLD_OBJ;

HELLO_WORLD_OBJ NewHelloWorld() {
	return NewObj("HELLO_WORLD");
}

void say (HELLO_WORLD_OBJ id) {
	Met3 (id,"say");
}

void helloYou(HELLO_WORLD_OBJ id,char *name) {
	SMet3 ("HELLO_WORLD",id,name);
}

Now your compiler will take care of type checking and you will write programs in a safeltier way. It's your choice. Note you can do the same using any programming language that can be interfaced to GNU/EDMA, for example using C++:

class HELLO_WORLD {
	private:
		OBJID   id;
	public:
		HELLO_WORLD() {id=NewObj("HELLO_WORLD");};
		void say (void) { Met3 (id,"say");
		static  void helloYou (char *name) {SMet3("HELLO_WORLD","helloYou",name);}
}

That can be used this simple way:

HELLO_WORLD  *o;

o=new HELLO_WORLD();
o->say();
o->helloYou("John");

This is the way most OO environments woks (COM, XPCOM, CORBA), the main drawback working this way is at the same time the main advantage, the intefaces get static so compiler can deal with them, but your application gets restricted to the interfaces availables at compile time.

FIXME: Check how COM deal with future components not available at compile time... fixes interfaces????

8. Final Words
--------------
In this papers we have showed how to manually build a GNU/EDMA component. GNU/EDMA is distributed with a tool called GNOME IDF Wizard that is able to build skeletons for most of the files required to build a component. Really it creates .IDF and .INES files completelly and for the implementation files you just need to add the desired parameters and the code itself.

In addition to this main objective we have introduced the concept of run-time interface compiling as a main diference with available OO environments nowdays.
