Using external libraries in a Morfik application

Morfik was designed from the ground up to be a web application development tool which allows developers to write code in a high level language, regardless of whether the code is for the browser or server side of the application.

While writing a Morfik application, you might wish to use some code that has been written by someone else, in order to reduce the development effort. This can be JavaScript code for the browser side of your application or source/binary libraries (DLLs, SOs) for your server side.

During the application compilation process, Morfik generates JavaScript code for the browser side of your application and intermediate source code for the server side. This intermediate code (which is in Object Pascal) is then compiled into the executable, through one of the supported platform compilers (pass 3 of the compile process).

The first thing that you need to know when bringing external code into Morfik is that it is a two-step task. The first step is making the code you wish to bring in available at the JavaScript (browser side) or Intermediate Object Pascal (server side). The second step is to make the code available to the Morfik High-level language compiler.

In order to illustrate how to do this, we will present some code snippets from the System module of the Morfik Framework

Step 1 – Bringing your code into the Morfik Application Framework space

For the browser side, this is almost immediate. Just add the JavaScript code file to your application’s Resource Repository and you are ready to go to the next step.

For server side code it is just as easy, but more options are available.

Object Pascal code - If your code is already written in Object Pascal, you can bring it right in. All you need to do is to include the path to your source in the advanced configuration of the Project Options. You might have to make small adjustments to your code, for compatibility, if it was written for Delphi. (This will not be necessary if you are using Delphi as your backend compiler.)

Dynamically Linked Libraries (DLL) - If you have a DLL (or shared object) that you wish to use from your Morfik application, you should write an Object Pascal import unit, which imports the functions you wish to have access to. The following example code demonstrates how a function from a DLL (or shared object) can be imported:

Function MyExternalFunction(Param : Integer) : Integer;
    TMyExternalFunction = Function (Param : Integer): Integer; StdCall;  
    DLLHandle   : THandle;       
    Proc        : Pointer;
    DLLHandle := LoadLibrary(' the path to my DLL ');       
    If DLLHandle <> 0 Then       
        Proc := GetProcAddress(DLLHandle,'MyExternalFunction');               
        If Assigned(Proc) Then               
            Result := TMyExternalFunction(Proc)(Param);                       

You also need to include the path to the import unit in the advanced configuration of the project options (as in the case of using Object Pascal code above).

In the example code above the calling convention modifier is set to StdCall. Depending on the language and the mechanism used to create the DLL you may need to specify a different calling convention. Please refer to Declaring the calling convention modifier for detailed explanation of available calling convention modifiers.

Step 2 – Making your code visible to the Morfik compiler

Once you have gone through the work in Step 1 and have made your JavaScript or your server side code accessible, you have to take an additional step to make the code available to the Morfik High-level language compiler.

In order to make the code available you have to create a module with the declaration of the functions or classes that you plan to use and mark them with the external metadata tag, informing where it is actually implemented.

For example, the FreeMem and GetMem functions in the System.mmd module are actually implemented in the SystemExt.pas unit. The following code informs the High-level compiler of that:

FX Code

Function  FreeMem(var P: Pointer; Size: Integer); ['External=SystemExt'];
Function  GetMem (var P: Pointer; Size: Integer); ['External=SystemExt'];

The same principle applied to these functions can be applied to classes, as well. The following code is an example of how to do it:

FX Code

Exception = Class(TException)
    FHelpContext: Integer;
    Constructor Create(Const Msg : String);
    Constructor CreateFmt(Const Msg : String;  Const Args  : Array Of Const);
    Constructor CreateRes(Ident : Integer);
    Constructor CreateResFmt(Ident : Integer; Const Args  : Array Of Const);
    Constructor CreateHelp(Const Msg : String; AHelpContext : Integer);
    Constructor CreateFmtHelp(Const Msg : String;  
                              Const Args : Array Of Const; 
                              AHelpContext: Integer);
    Constructor CreateResHelp   (Ident : Integer; AHelpContext: Integer);
    Constructor CreateResFmtHelp(Ident : Integer; 
                                 Const Args  : Array Of Const; 
                                 AHelpContext: Integer);
    Property HelpContext : Integer Read FHelpContext Write FHelpContext;
    Property Message : String Read Msg Write Msg;
End; ['External=SystemExt'];

These examples are of functions and classes which are made visible to all Morfik code through the System.mmd module, but which is actually implemented in the SystemExt.pas Object Pascal unit.

Of course, all of these examples are server side, but the browser side is even easier. On the Browser side you might be referencing some functionality which is made available by the browser itself, or by a JavaScript file. The two lines of code that follow show how to handle both situations, respectively.

FX Code

Function IsModuleLoaded(m : String) : Boolean; ['External='];
Function getDomainSuffix(d : String) : String;  ['External=brlJLib'];

The next code snippet is the declaration of the TXMLHTTPRequest class which is implemented within the browser itself.

FX Code

TXMLHTTPRequest = Class
    responseText : String;
    responseXML : String;
    onreadystatechange : Pointer;
    readyState : Integer;
    status : Integer;
    wrapper: Pointer;
    Function open(Method, Url : String; Async : Boolean; 
                  User, Password : String);
    Function send(Body : String);
    Function setRequestHeader(HeaderName, HeaderValue : String);
    Function abort;
End; ['External='];

As you can notice, whenever a function or class is implemented in the browser itself the right hand side of the equals sign for the External metadata tag is left empty.

See Also

Back to top