Re: [Rd] external pointers

2005-12-11 Thread Mark.Bravington
I don't entirely follow Ross's outline below (?how does the R object
'opaque' get to feature in the call to 'docompute'?), but I have written
large amounts of R-linked Delphi code with persistent Delphi objects,
using only the '.C' interface and no external pointers. You might find
this useful if you want to avoid the complexities of '.Call' and SEXPs
etc. NB the C/Delphi distincition is not important here.

(i)The first '.C' call uses Delphi code to allocate (using Delphi's own
memory manager) and set up a persistent object that R doesn't know
about. The Delphi code then returns an "opaque" integer-valued handle to
R, which is the address of the object in the Delphi DLL's world.

(ii) For subsequent '.C' calls to Delphi from R, I pass in the handle,
which I then typecast to an object pointer inside Delphi. Hence I can
"find" the persistent object. This way there can be several persistent
objects simultaneously-- I'm not limited to global variables in the
Delphi DLL.

(iii) There is a final cleanup '.C' call which deallocates the
persistent object. I sometimes also automate the destruction in the
cleanup code of the DLL, just in case the R user forgets to cleanup. 

I have also gotten this to work after replacing Delphi's memory manager
with R's own-- there was no difference (but apparently no point either,
from what I've been told).

There are some further notes inside a PDF on Duncan Murdoch's page:

http://www.stats.uwo.ca/faculty/murdoch/software/compilingDLLs/pascal.ht
ml

The notes are very Delphi-flavoured (and refer to S not R, since I've
used the method both with S-plus and R) but the point should-- or
might-- be clear.

HTH

Mark

Mark Bravington
CSIRO Mathematical & Information Sciences
Marine Laboratory
Castray Esplanade
Hobart 7001
TAS

ph (+61) 3 6232 5118
fax (+61) 3 6232 5012
mob (+61) 438 315 623
 

> -Original Message-
> From: [EMAIL PROTECTED] 
> [mailto:[EMAIL PROTECTED] On Behalf Of Byron Ellis
> Sent: Saturday, 10 December 2005 11:24 AM
> To: Ross Boylan
> Cc: R Development List
> Subject: Re: [Rd] external pointers
> 
> use a C finalizer...
> 
> void MyObject_finalize(SEXP opaque) {
>   MyObject *obj = (MyObject*)R_ExternalPtrAddr(opaque);
>   if(NULL != obj) delete obj;
> }
> 
> and in your setup code...
> 
> PROTECT(p = R_MakeExternalPtr(...));
> R_RegisterCFinalizer(p,MyObject_finalize);
> 
> 
> 
> 
> 
> 
> On Dec 9, 2005, at 3:04 PM, Ross Boylan wrote:
> 
> > I have some C data I want to pass back to R opaquely, and 
> then back to 
> > C.  I understand external pointers are the way to do so.
> >
> > I'm trying to find how they interact with garbage collection and 
> > object lifetime, and what I need to do so that the memory 
> lives until 
> > the calling R process ends.
> >
> > Could anyone give me some pointers?  I haven't found much 
> > documentation.
> > An earlier message suggested looking at simpleref.nw, but I 
> can't find 
> > that file.
> >
> > So the overall pattern, from R, would look like opaque <- 
> setup(arg1, 
> > arg2, )  # setup calls a C fn docompute(arg1, argb, opaque)  # 
> > many times. docompute also calls C # and then when I return 
> opaque and  
> > the memory it's wrapping get #cleaned up.  If necessary I could do
> > teardown(opaque)  # at the end
> >
> > "C" is actually C++ via a C interface, if that matters.  In 
> > particular, the memory allocated will likely be from the 
> C++ run-time, 
> > and needs C++ destructors.
> >
> > -- 
> > Ross Boylan  wk:  (415) 514-8146
> > 185 Berry St #5700   
> [EMAIL PROTECTED]
> > Dept of Epidemiology and Biostatistics   fax: (415) 514-8150
> > University of California, San Francisco
> > San Francisco, CA 94107-1739 hm:  (415) 550-1062
> >
> > __
> > R-devel@r-project.org mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-devel
> 
> ---
> Byron Ellis ([EMAIL PROTECTED])
> "Oook" -- The Librarian
> 
> __
> R-devel@r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
> 
>

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] external pointers

2005-12-11 Thread Simon Urbanek
Mark,

On Dec 12, 2005, at 7:48 AM, <[EMAIL PROTECTED]> wrote:

> (i)The first '.C' call uses Delphi code to allocate (using Delphi's  
> own memory manager) and set up a persistent object that R doesn't  
> know about. The Delphi code then returns an "opaque" integer-valued  
> handle to R, which is the address of the object in the Delphi DLL's  
> world.

That's a bad idea for a couple of reasons, the main being that  
integer is not guaranteed to be able to hold a pointer - it won't  
work on any 64-bit platform. Second drawback is that you have no way  
to link the life of the R object to your Delphi object, because there  
is no way gc will tell you that the object is gone. This will lead to  
memory leaks. [Been there, done that ;)] Both issues are solved by  
the external pointers.

> (iii) There is a final cleanup '.C' call which deallocates the  
> persistent object. I sometimes also automate the destruction in the  
> cleanup code of the DLL, just in case the R user forgets to cleanup.

How do you make sure the no one uses the now invalid integer value?  
There can be many copies of your proxy object around and they all  
point to nirvana ...

Cheers,
Simon

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] external pointers

2005-12-11 Thread Mark.Bravington
Hi Simon

Thanks for that... see below for my feeble counterblasts! (And two
questions.)

> Mark,
> 
> On Dec 12, 2005, at 7:48 AM, <[EMAIL PROTECTED]> wrote:
> 
> > (i)The first '.C' call uses Delphi code to allocate (using Delphi's 
> > own memory manager) and set up a persistent object that R 
> doesn't know 
> > about. The Delphi code then returns an "opaque" 
> integer-valued handle 
> > to R, which is the address of the object in the Delphi DLL's world.
> 
> That's a bad idea for a couple of reasons, the main being 
> that integer is not guaranteed to be able to hold a pointer - 
> it won't work on any 64-bit platform. 

Very true, though 64 bit systems are not a big worry for Delphi 6.0
writers... ;) I did once speculate about hacking around this sort of
thing by encoding into character strings instead of integers, uggg.

> Second drawback is that 
> you have no way to link the life of the R object to your 
> Delphi object, because there is no way gc will tell you that 
> the object is gone. This will lead to memory leaks. [Been 
> there, done that ;)] Both issues are solved by the external pointers.

> 
> > (iii) There is a final cleanup '.C' call which deallocates the 
> > persistent object. I sometimes also automate the destruction in the 
> > cleanup code of the DLL, just in case the R user forgets to cleanup.
> 
> How do you make sure the no one uses the now invalid integer value?  
> There can be many copies of your proxy object around and they 
> all point to nirvana ...

Sorry, that was lack of clarity on my part about what I meant by
"persistent". Whenever I use this mechanism, I'm careful to ensure that
the C/Delphi objects only have lifetimes *within* a function, and to
include an 'on.exit' call to the "destructor"-- I would never  create
global objects pointing to ephemeral C structures. Admittedly, this
relies on programming self-discipline, and has no cast-iron anti-nirvana
mechanism! Ross' original query seems very much along these lines,
though.

If I was really creating global persistent objects, then 'externalptr'
would definitely be much better.

Where would be best to read about externalptr? I'm having trouble
finding material in the manuals or the site-search.

And would I need to use all the .Call machinery and C headers and SEXP
etc in order to handle externalptr objects?

> 
> Cheers,
> Simon

bye
Mark

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel


Re: [Rd] external pointers

2005-12-11 Thread Roger Bivand
On Mon, 12 Dec 2005 [EMAIL PROTECTED] wrote:

> Hi Simon
> 
> Thanks for that... see below for my feeble counterblasts! (And two
> questions.)
> 
> > Mark,
> > 
> > On Dec 12, 2005, at 7:48 AM, <[EMAIL PROTECTED]> wrote:
> > 
> > > (i)The first '.C' call uses Delphi code to allocate (using Delphi's 
> > > own memory manager) and set up a persistent object that R 
> > doesn't know 
> > > about. The Delphi code then returns an "opaque" 
> > integer-valued handle 
> > > to R, which is the address of the object in the Delphi DLL's world.
> > 
> > That's a bad idea for a couple of reasons, the main being 
> > that integer is not guaranteed to be able to hold a pointer - 
> > it won't work on any 64-bit platform. 
> 
> Very true, though 64 bit systems are not a big worry for Delphi 6.0
> writers... ;) I did once speculate about hacking around this sort of
> thing by encoding into character strings instead of integers, uggg.
> 
> > Second drawback is that 
> > you have no way to link the life of the R object to your 
> > Delphi object, because there is no way gc will tell you that 
> > the object is gone. This will lead to memory leaks. [Been 
> > there, done that ;)] Both issues are solved by the external pointers.
> 
> > 
> > > (iii) There is a final cleanup '.C' call which deallocates the 
> > > persistent object. I sometimes also automate the destruction in the 
> > > cleanup code of the DLL, just in case the R user forgets to cleanup.
> > 
> > How do you make sure the no one uses the now invalid integer value?  
> > There can be many copies of your proxy object around and they 
> > all point to nirvana ...
> 
> Sorry, that was lack of clarity on my part about what I meant by
> "persistent". Whenever I use this mechanism, I'm careful to ensure that
> the C/Delphi objects only have lifetimes *within* a function, and to
> include an 'on.exit' call to the "destructor"-- I would never  create
> global objects pointing to ephemeral C structures. Admittedly, this
> relies on programming self-discipline, and has no cast-iron anti-nirvana
> mechanism! Ross' original query seems very much along these lines,
> though.
> 
> If I was really creating global persistent objects, then 'externalptr'
> would definitely be much better.
> 
> Where would be best to read about externalptr? I'm having trouble
> finding material in the manuals or the site-search.
> 
> And would I need to use all the .Call machinery and C headers and SEXP
> etc in order to handle externalptr objects?

One package using externalptr is rgdal - Tim Keitt wrote the bindings to
the external GDAL library for reading raster images to first return a
pointer to a dataset (on disk) opened by GDAL, then to use the object to
retrieve (parts of) the data. Most of the .Call/SEXP machinery is there
(for the C++ case, GDAL is C++, so GDAL manages its own memory for its
objects). The package also uses S4 classes, which may be overkill for your
purposes.

Roger

> 
> > 
> > Cheers,
> > Simon
> 
> bye
> Mark
> 
> __
> R-devel@r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
> 

-- 
Roger Bivand
Economic Geography Section, Department of Economics, Norwegian School of
Economics and Business Administration, Helleveien 30, N-5045 Bergen,
Norway. voice: +47 55 95 93 55; fax +47 55 95 95 43
e-mail: [EMAIL PROTECTED]

__
R-devel@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel