Using ABCp from Delphi
Contents
1. Introduction
2. Import ABCp functions
3. Test application
3.1 User
interface
3.2 The
code
4. Conclusion
1. Introduction
One of the objectives for ABCp is to be easily embeddable
and "language independent" to the maximum possible extent.
The choice of ANSI C as language for the library has
been made for maximizing the chance of success.
This document describes how to use the library (compiled
as a DLL so to be dinamically linked) from Borland Delphi.
The objective is extend the proof of concept to check
how easy (or difficult) is to use ABCp from other languages.
2. Import ABCp functions
First of all we have to import the functions from the
ABCp DLL. The following unit named "abcp.pas" will do
the job:
unit abcp;
interface
function abcScanFile(filename: PChar; handler : pointer) : integer;
cdecl; external 'abcp.dll' name '_abcScanFile';
function abcScanString(buffer: PChar; handler : pointer) : integer;
cdecl; external 'abcp.dll' name '_abcScanString';
function abcToken(s: Pointer): integer;
cdecl; external 'abcp.dll' name '_abcToken';
function abcTokenName(n: integer) : Pchar;
cdecl; external 'abcp.dll' name '_abcTokenName';
function abcState(s: Pointer): integer;
cdecl; external 'abcp.dll' name '_abcState';
function abcStateName(s: integer): Pchar;
cdecl; external 'abcp.dll' name '_abcStateName';
function abcString(s: Pointer): PChar;
cdecl; external 'abcp.dll' name '_abcString';
function abcFilename(s: Pointer): PChar;
cdecl; external 'abcp.dll' name '_abcFilename';
function abcLine(s: Pointer): integer;
cdecl; external 'abcp.dll' name '_abcLine';
function abcColumn(s: Pointer): integer;
cdecl; external 'abcp.dll' name '_abcColumn';
implementation
end.
|
To increase readibility, the interface functions are
in bold.
Note that the two enum's (Tokens and States) have been
represented as integers in Pascal, they could well be represented
as enumerated type.
If you have a look at "abcp.h "
you can see how easy has been to create the above unit.
3. Test application
In the download section you
will find a test application with all the source (Delphi 6), and
the abcp.dll.
I do apologize for the poor interface design, and
uselessness of the example, please consider it's only a proof of
concept!!!
3.1 The user interface
The test application user interface is a single window
split in two sections:
On the left you can write a piece of music in ABC and
on the right (once Scan has been pressed) you will see the tokens
returned by the abcScanString() function.
3.2 The code
Again, the "handler interface" has been used
for this example. This is the only interface
defined so far, is very low level but it gives you the ability of
interpreting ABC files (more or less) easily.
There are only two relevant functions in the code.
The function that starts the scanning:
procedure Tfrm_abc.btn_scanClick(Sender: TObject);
var r: integer;
begin
r := abcScanString(PChar(txt_abc.Text),@handler)
end; |
and the handler that gets called at each token.
function handler(h:pointer):integer; cdecl;
var i:integer;
begin
i:=frm_abc.lst_toks.Items.Add( abcStateName(abcState(h)) + ' ' +
abcTokenName(abcToken(h)) + ' ' +
abcString(h));
handler:=0;
end; |
The handler is a "normal" pascal function, only
cdecl has been added to ensure that
the parameters are passed correctly.
4. Conclusion
It seems that using ABCp from another language is
not too difficult.
It's fair to say that for each language, an interface
needs to be built (like our abcp.pas unit) that encapsulate the
ABCp API. How complex is to create it will depend on the language
at hand.
Next steps for expanding the proof of concept in this
direction is to target Kylix on Linux (for his similarity with Delphi),
VB and Java.
|