[Rd] headerfile translation to Delphi (Pascal) completed

Hans-Peter gchappi at gmail.com
Wed Apr 12 11:42:05 CEST 2006


Hi,

I am happy to announce that I finished the translation of almost all
LGPL'ed R headerfiles to Delphi. As a test I did several demos which
basically contain delphized versions of all the examples of chapter 5
in "Writing R Extensions".

Please have a look in the attachments for details
(DemosAndHeaders.txt), more information (Readme.txt) and an example of
how it looks (Convolve.pas).

The final version will be released some time later* as GPL.

By now I'd like to make available the sources to all interested R
regulars in order to try out and - maybe - to get some feedback. Just
drop me a mail and I'm happy to send you the sources**.

(Btw, I worked with Delphi 2006 (tested with D6 also). I don't
know/use the FreePascal compiler so it's windows only (at least for
the moment)).

Best regards,
Hans-Peter


*After R2.3; also I need to do larger tests and think about some kind
of testframework
**I already sent them to the few persons I know who might be interested


 - - -
| Hans-Peter Suter, Dipl. Natw. ETH / SW-Entwickler
| Treetron Umweltinformatik, Zuerich Tel +41(1)242 22 55
| mailto: <firstname>.<name>@treetronPUNKTch
| or: gchappi at gmail.com
-------------- next part --------------
DEMOS
========================================================
Available:
- Convolve | - RegisteredConvolve | - Initialize |
- GlobalVariables | - AcrossTheBoard

In each folder is a specific script _rscript and in the
Demo folder two global ones (_rscript/_rscriptMultiple)
--------------------------------------------------------

Convolve
--------
The first demo presents the convolve examples from the manual
"Writing R Extensions" in a "Delphi-translated" version. The 
three interface functions .C, .Call and .External are used and
the application of some macros in Rinternals.h and Rdefines.h
(which become rhRInternal.pas and rhRDefines.pas) is shown.

RegisteredConvolve
------------------
"RegisteredDemoEx.dll" shows how to register a Delphi function 
in the "R_init_<dll-name>" call.

[The RegisteredConvDemo was the first attempt but the freely 
called register method "RegisterConvolveRoutines" still crashes 
in some circumstances (see _rscriptMultiple.R) for unknown reason]

Initialize
----------
This important demo prints the sequence of the initialize and
finalize calls. Can be used as a template.

Global variables
----------------
Delphi cannot directly use global variables in DLL's. We have
to assign them manually. This demo was our test ground. The units 
rhR, rhRInternal and rhR have such variables. Search for the
overloaded function ToRVarsArr to find the relevant places.

Across the board
----------------
An extensive demo with basically all the remaining examples from
"Writing R Extensions". We failed with print attributes (bloody Lisp!)
and left out parsing R code, but the rest is here.




HEADER UNITS
========================================================
[Quality: 1: tested, 2: anecdotic tests, 3: compiles, 4: unfinished
Tested on R 2.2.1 and 2.3.alpha]
        
R Headerfile          becomes      Quality  Delphi unit
----------------------------------------------------------
Applic.h                --->         3      rhApplic.pas
Arith.h                 ~~~>         2      rhR.pas
BLAS.h                  --->         3      rhBlas.pas
Boolean.h               ~~~>         2      rhTypesAndConsts.pas
Callbacks.h             --->         3      rhCallbacks.pas
Complex.h               ~~~>         2      rhTypesAndConsts.pas
Constants.h             ~~~>         3      rhTypesAndConsts.pas
Error.h                 ~~~>         2      rhR.pas
eventloop.h             xxxx         4      (no entry points, probably unix-only)
GraphicsBase.h          (??)         4      (partly done, some types GPL only? FIXME)
GraphicsDevice.h        --->         3      rhGraphicsDevice.pas 
GraphicsEngine.h        --->         3      rhGraphicsEngine.pas
Lapack.h                xxxx         4      (MAYBE LATER - exported in Rlapack.dll)
libextern.h             (xx)         -      (contains defines - not relevant)
Linpack.h               xxxx         4      (MAYBE LATER)
Memory.h                ~~~>         3      rhR.pas
Print.h                 ~~~>         2      rhR.pas
PrtUtil.h               --->         3      rhPrtUtil.pas
R-ftp-http.h            --->         3      rhRftpHttp.pas
R.h                     ~~~>         3      rhTypesAndConsts.pas
Random.h                ~~~>         3      rhR.pas / rhTypesAndConsts.pas
RConverters.h           --->         3      rhRConverters.pas
Rdefines.h              --->         2      rhRDefines.pas
Rdynload.h              --->         2      rhRDynload.pas
Rdynpriv.h              ~~~>         2      rhRDynload.pas
Rgraphics.h             --->         3      rhRGraphics.pas
Riconv.h                --->         3      rhRIconv.pas
Rinlinedfuns.h          xxxx         -      (probably(?) only Gnu C compiler relevant)
Rinternals.h            --->         2      rhRInternals
" (use Internal stuff)  ~~~>         3      rhRUseInternals (NOT TO BE PUBLISHED) 
Rlapack.h               xxxx         4      (MAYBE LATER)
RS.h                    ~~~>         3      rhR.pas
RX55.h                  xxxx         -      (probably (?) unix-only)
S.h                     xxxx         4      (MAYBE LATER)
Utils.h                 --->         3      rhUtils.pas

-------------- next part --------------
- - - - - - - - - - - - -
- - -   D R A F T   - - -
- - - - - - - - - - - - -

Port of R header files to Delphi (Pascal)


--- CONTENT ---

. Introduction
. Getting started
. Translation conventions
. Use_RInternal (Rinternals.h)
. License


--- INTRODUCTION ---

This port of the R headers to Delphi offers a lowlevel interface between the
powerful R statistical computing system and Delphi, a pascal derived language
and arguably the most productive development environment around.

Most LGPL headers have been translated. As we took care to keep very close
to the original header files one can take over the examples from "Writing R
Extensions" almost one to one. Within the demos we explored how to load a
delphi based DLL from R and how to call the R API from it. We didn't do the
opposite, namely link the R.dll from a standalone Delphi application.

This project does - of course - in no way promote the widespread use of pascal
code within R, it's about special cases, particulary on the windows platform.
The port has been done with D2006 and has been tested on D6 also. It probably
won't run on <= D5 (e.g. varargs) and we didn't try with FreePascal either.

A final word about testing. The demos run fine (on R2.2.1 and 2.3.alpha),
but for the other (majority) part of the code, the only thing we know is, that
it compiles... More tests and applications are planned, but a thorough testing
(DUnit?) is probably out of question (just too much code).


--- GETTING STARTED ---

It's really easy.

Do check the document DemosAndHeaders.txt:
  - There's a list of the translated headers and their corresponding unit.
  - More important, there's also a list of all demos. The demo source code is
    the main point where you can hear about interfacing R and Delphi.

Other files that may be of interest are: BugsAndQuestions.txt and History.txt


--- TRANSLATION CONVENTIONS ---

Motto: As close as possible to the syntax/naming of the original headers

Changes:
  - most prefixes ("Rf_", "R_", "do_", ...) and suffixes ("_t") are gone.
    An exception is "S_" which is shortened to "S"
  - the underscores ("_") are gone too. CamelCaseStyleConvention is used.
  - different versions (Rf_asChar, asChar) become one (riAsChar)
  - the letter following R (or S) is written in capital (e.g. aSExp)
  - the following prefixes are used (to avoid name clashes):
  	- a small "r" (e.g.rNormRand), except for
  	- a small "ri" for things in Rinternals (e.g. riReal) and except
  	- a small "rd" for things in Rdefines   (e.g. rdNumericPointer)
	 [- low level functions contained in the unit rhRUseInternals.pas
	    have the prefix "rui". (This is too lowlevel and not delivered)]

Filenames: Pprefixed with "rh" (R header) or "rhu" (R header utils).

Delphi conventions:
  - types start with an "a", pointers with "p" (e.g. R_len_t becomes aRLen)
  - constants start with prefix "The" (global) or "the" (local)
  - variables start with capital (global) or small (local) letter
  - function start with capital prefixed by "r", "ri/rui" or "rd"
	- arguments start with an underscore followed by a small letter

Misc:
  - Pointer type arguments have been translated as pointers
    (E.g. "x *int" becomes "_x: pInteger" and NOT "var _x: integer")
  - Unfortunately there are two forms of length (LENGTH and length/Rf_length)
    in the header file Rinternals. The
    - vector access macro LENGTH becomes riLength and
    - the ??? length(x)/Rf_length become rLength.


--- USE_RINTERNAL (RINTERNALS.H) ---

The file "Rinternals.h" contains two sets of functions: one with "real"
functions who are exported in the R.dll and one with functions that use
the structs (records) directly to access the data. The second is intended
for use within R itself and is protected by the "USE_RINTERNALS" define.
While both "sets" have been translated, only rhRInternals.pas is distributed
for now. This may change upon need/request.


--- LICENSE ---

The Delphi port of the R header files will be published under a dual
license (GPL v2.1 / proprietary) later. (End of 2006 at the latest)*
                              ---
[Our port is exclusively based on R header files with are licensed under
the terms of the GNU Lesser General Public License (version 2.1 or above).
                               -
R is a computer language for statistical data analysis. It is
Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
Copyright (C) 1999-2006   The R Development Core Team
and published under the terms of the GNU General Public License.]
                              ---
The software is provided in the hope that it will be useful but without any
express or implied warranties, including, but not without limitation, the
implied warranties of merchantability and fitness for a particular purpose.
                              ---
Copyright (C) 2006 by Hans-Peter Suter, Treetron GmbH, Switzerland.
All rights reserved.



*
Until then the sources should be treated as closed source and only be available
to known R regulars. Reasons for this: 1) I'd like to incorporate feedback and
2) I really need to try out the code in some bigger application to be sure that
it works reliably. 3) 2.3 should be released first and 4) There must be some sort
of a testframework to make sure that new releases don't break basic things.

Have fun,
Hans-Peter
-------------- next part --------------
unit Convolve;

{ "Delphized" version of simple examples which convolve two finite sequences.
  See: Writing R Extensions. Version 2.3.0 (2006-02-19). ISBN 3-900051-11-9.
                              ---
  The software is provided in the hope that it will be useful but without any
  express or implied warranties, including, but not without limitation, the
  implied warranties of merchantability and fitness for a particular purpose.
                              ---
  11.3.2006 - Hans-Peter Suter, Treetron, Switzerland.
                              ---                                              }

{==============================================================================}
interface
uses
  rhRInternals, rhTypesAndConsts;

  { ConvC - call our convolve using .C }
  { We use pointer type arguments as they are closer to the original C code.
    See in implementation for an example with parameters passed by reference }
procedure ConvC( _a: pDoubleArr; _na: pInteger;
                 _b: pDoubleArr; _nb: pInteger;
                 _ab: pDoubleArr ); cdecl;

  { ConvCallRInternals - call our convolve using .Call and Rinternals }
function ConvCallRInternals( _a, _b: pSExp ): pSExp; cdecl;

  { ConvCallRDefines - call our convolve using .Call and Rdefines }
function ConvCallRDefines( _a, _b: pSExp ): pSExp; cdecl;

  { ConvExternalRInternals - call our convolve using .External and Rinternals }
function ConvExternalRInternals( _args: pSExp ): pSExp; cdecl;

  { call our convolve using .External and Rdefines }
{ nothing new to see, skipped }


{==============================================================================}
implementation
uses
  rhRDefines;

{ ConvC }

// Example for declaration/code with PARAMETERS PASSED BY REFERENCE
//procedure ConvC( var _a: aDoubleArr; var _na: integer;
//                 var _b: aDoubleArr; var _nb: integer;
//                 var _ab: aDoubleArr ); cdecl;
//  var
//    i, j, nab: integer;
//  begin
//    nab:= _na + _nb - 1;
//    for i:= 0 to nab - 1 do _ab[i]:= 0.0;
//    for i:= 0 to _na - 1 do begin
//      for j := 0 to _nb - 1 do begin
//        _ab[i + j]:= _ab[i + j] + _a[i]*_b[j]
//      end {for};
//    end {for};
//  end {ConvC};

procedure ConvC( _a: pDoubleArr; _na: pInteger;
                 _b: pDoubleArr; _nb: pInteger;
                 _ab: pDoubleArr ); cdecl;
  var
    i, j, nab: integer;
  begin
    nab:= _na^ + _nb^ - 1;
    for i:= 0 to nab - 1 do _ab[i]:= 0.0;
    for i:= 0 to _na^ - 1 do begin
      for j := 0 to _nb^ - 1 do begin
        _ab[i + j]:= _ab[i + j] + _a[i]*_b[j]
      end {for};
    end {for};
  end {ConvC};


{ ConvCallRInternals }

function ConvCallRInternals( _a, _b: pSExp ): pSExp; cdecl;
  var
    i, j, na, nb, nab: aRLen;
    pxa, pxb, pxab: pDoubleArr;
  begin
    _a:= riProtect( riCoerceVector( _a, setRealSxp ) );
    _b:= riProtect( riCoerceVector( _b, setRealSxp ) );
    na:= riLength( _a ); nb:= riLength( _b ); nab:= na + nb - 1;
    result:= riProtect( riAllocVector( setRealSxp, nab ) );

    pxa:= riReal( _a ); pxb:= riReal( _b );
    pxab:= riReal( result );

    for i := 0 to nab - 1 do pxab[i]:= 0.0;
    for i := 0 to na - 1 do begin
      for j := 0 to nb - 1 do begin
        pxab[i + j]:= pxab[i + j] + pxa[i]*pxb[j]
      end {for};
    end {for};

    riUnprotect( 3 );
  end {ConvCallRInternals};


{ ConvCallRDefines }

function ConvCallRDefines( _a, _b: pSExp ): pSExp; cdecl;
  var
    i, j, na, nb, nab: integer;
    pxa, pxb, pxab: pDoubleArr;
    ab: pSExp;
  begin
    _a:= riProtect( rdAsNumeric( _a ) );
    _b:= riProtect( rdAsNumeric( _b ) );
    na:= riLength( _a ); nb:= riLength( _b ); nab:= na + nb - 1;
    ab:= riProtect( rdNewNumeric( nab ) );

    pxa:= rdNumericPointer( _a ); pxb:= rdNumericPointer( _b );
    pxab:= rdNumericPointer( ab );

    for i := 0 to nab - 1 do pxab[i]:= 0.0;
    for i := 0 to na - 1 do begin
      for j := 0 to nb - 1 do begin
        pxab[i + j]:= pxab[i + j] + pxa[i]*pxb[j]
      end {for};
    end {for};

    riUnprotect( 3 );
    result:= ab;
  end {ConvCallRDefines};


{ ConvExternalRInternals }

function ConvExternalRInternals( _args: pSExp ): pSExp; cdecl;
  var
    i, j, na, nb, nab: aRLen;
    pxa, pxb, pxab: pDoubleArr;
    a, b, ab: pSExp;
  begin
    a:= riProtect( riCoerceVector( riCadr( _args ), setRealSxp ) );
    b:= riProtect( riCoerceVector( riCaddr( _args ), setRealSxp ) );
    na:= riLength( a ); nb:= riLength( b ); nab:= na + nb - 1;
    ab:= riProtect( riAllocVector( setRealSxp, nab ) );

    pxa:= riReal( a ); pxb:= riReal( b );
    pxab:= riReal( ab );

    for i := 0 to nab - 1 do pxab[i]:= 0.0;
    for i := 0 to na - 1 do begin
      for j := 0 to nb - 1 do begin
        pxab[i + j]:= pxab[i + j] + pxa[i]*pxb[j]
      end {for};
    end {for};

    riUnprotect( 3 );
    result:= ab;
  end {ConvExternalRInternals};


end {Convolve}.



More information about the R-devel mailing list