Using external libraries in a Morfik application
From Morfik Wiki
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; Type TMyExternalFunction = Function (Param : Integer): Integer; StdCall; Var DLLHandle : THandle; Proc : Pointer; Begin DLLHandle := LoadLibrary(' the path to my DLL '); If DLLHandle <> 0 Then Begin Proc := GetProcAddress(DLLHandle,'MyExternalFunction'); If Assigned(Proc) Then Result := TMyExternalFunction(Proc)(Param); FreeLibrary(DLLHandle); End; End;
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'];
| BX Code |
|---|
Public External Sub FreeMem(ByRef P As Pointer, Size As Integer) :{"External=SystemExt"} Public External Sub GetMem (ByRef P As Pointer, Size As Integer) :{"External=SystemExt"} |
| CX Code |
|---|
public external void FreeMem(ref Pointer P, Integer Size); ["External=SystemExt"] public external void GetMem(ref Pointer P, Integer Size); ["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) Private FHelpContext: Integer; Public 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'];
| BX Code |
|---|
Public External Class Exception Inherits TException Private FHelpContext As Integer Public Overloads Sub New(Const Msg As String) Public Overloads Sub New(Const Msg As String, Const Args As Const()) Public Overloads Sub New(Ident As Integer) Public Overloads Sub New(Ident As Integer, Const Args As Const()) Public Overloads Sub New(Const Msg As String, AHelpContext As Integer) Public Overloads Sub New(Const Msg As String, Const Args As Const(), AHelpContext As Integer) Public Overloads Sub New(Ident As Integer, AHelpContext As Integer) Public Overloads Sub New(Ident As Integer, Const Args As Const(), AHelpContext As Integer) Public Property HelpContext As Integer End Property Public Property Message As String End Property End Class :{"External=SystemExt"} |
| CX Code |
|---|
public external class Exception : TException { private Integer FHelpContext; public Exception(const String Msg); public Exception(const String Msg, const const[] Args); public Exception(Integer Ident); public Exception(Integer Ident, const const[] Args); public Exception(const String Msg, Integer AHelpContext); public Exception(const String Msg, const const[] Args, Integer AHelpContext); public Exception(Integer Ident, Integer AHelpContext); public Exception(Integer Ident, const const[] Args, Integer AHelpContext); public Integer HelpContext { } public String Message { } } ["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'];
| BX Code |
|---|
Public External Function IsModuleLoaded(m As String) As Boolean :{"External="} Public External Function getDomainSuffix(d As String) As String :{"External=brlJLib"} |
| CX Code |
|---|
public external Boolean IsModuleLoaded(String m); ["External="] public external String getDomainSuffix(String d); ["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='];
| BX Code |
|---|
Public External Class TXMLHTTPRequest Public responseText As String Public responseXML As String Public onreadystatechange As Pointer Public readyState As Integer Public status As Integer Public wrapper As Pointer Public Sub open(Method As String, Url As String, Async As Boolean, User As String, Password As String) Public Sub send(Body As String) Public Sub setRequestHeader(HeaderName As String, HeaderValue As String) Public Sub abort End Class :{"External="} |
| CX Code |
|---|
public external class TXMLHTTPRequest { public String responseText; public String responseXML; public Pointer onreadystatechange; public Integer readyState; public Integer status; public Pointer wrapper; public void open(String Method, String Url, Boolean Async, String User, String Password); public void send(String Body); public void setRequestHeader(String HeaderName, String HeaderValue); public void abort(); } ["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

