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}.