Hi,
I have a package where I'm calling an R function (say "foo") from C
code. "foo" is in the same package, but is not exported. I construct
the call using lang1(install("foo")), but to eval it I need the
package's environment. Is there a way to do this? Passing the correct
environment through .Call() is not an option.
Right now, I'm getting the environment first using something like
rho = PROTECT(eval(lang2(install("environment"), install("bar")),
R_GlobalEnv))
where bar _is_ exported. However, this doesn't work if the package is
loaded but not attached, and is also risky because someone might
define another "bar" that is found first.
One solution that might work is to make 'rho' a global variable and
assign the correct value when the package is loaded. Is that a good
idea? How should I PROTECT it?
-Deepayan
Getting hold of a package's environment from C code
11 messages · Duncan Murdoch, Deepayan Sarkar, Seth Falcon +2 more
On 10/22/2006 3:56 PM, Deepayan Sarkar wrote:
Hi,
I have a package where I'm calling an R function (say "foo") from C
code. "foo" is in the same package, but is not exported. I construct
the call using lang1(install("foo")), but to eval it I need the
package's environment. Is there a way to do this? Passing the correct
environment through .Call() is not an option.
Right now, I'm getting the environment first using something like
rho = PROTECT(eval(lang2(install("environment"), install("bar")),
R_GlobalEnv))
where bar _is_ exported. However, this doesn't work if the package is
loaded but not attached, and is also risky because someone might
define another "bar" that is found first.
In R code, you could use getNamespace("pkg") to get the namespace
environment. I haven't tried this, but I'd assume
PROTECT(rho = eval(lang2(install("getNamespace"),
ScalarString(mkChar("pkg"))));
(or something like it) would be the C equivalent.
>
> One solution that might work is to make 'rho' a global variable and
> assign the correct value when the package is loaded. Is that a good
> idea? How should I PROTECT it?
I'd say to avoid globals if you can, and I think you can here.
Duncan Murdoch
On 10/22/06, Duncan Murdoch <murdoch at stats.uwo.ca> wrote:
On 10/22/2006 3:56 PM, Deepayan Sarkar wrote:
Hi,
I have a package where I'm calling an R function (say "foo") from C
code. "foo" is in the same package, but is not exported. I construct
the call using lang1(install("foo")), but to eval it I need the
package's environment. Is there a way to do this? Passing the correct
environment through .Call() is not an option.
Right now, I'm getting the environment first using something like
rho = PROTECT(eval(lang2(install("environment"), install("bar")),
R_GlobalEnv))
where bar _is_ exported. However, this doesn't work if the package is
loaded but not attached, and is also risky because someone might
define another "bar" that is found first.
In R code, you could use getNamespace("pkg") to get the namespace
environment. I haven't tried this, but I'd assume
PROTECT(rho = eval(lang2(install("getNamespace"),
ScalarString(mkChar("pkg"))));
(or something like it) would be the C equivalent.
Thanks, that works perfectly. -Deepayan
"Deepayan Sarkar" <deepayan.sarkar at gmail.com> writes:
On 10/22/06, Duncan Murdoch <murdoch at stats.uwo.ca> wrote:
In R code, you could use getNamespace("pkg") to get the namespace
environment. I haven't tried this, but I'd assume
PROTECT(rho = eval(lang2(install("getNamespace"),
ScalarString(mkChar("pkg"))));
(or something like it) would be the C equivalent.
Perhaps: R_FindNamespace(mkString(where)) + seth
Seth Falcon <sfalcon at fhcrc.org> writes:
Perhaps: R_FindNamespace(mkString(where))
Sorry, this won't help you for package-level code as this function is part of the internal use only API. It would be nice to have access to it or a similar function from C in package code.
On Sun, 22 Oct 2006, Deepayan Sarkar wrote:
On 10/22/06, Duncan Murdoch <murdoch at stats.uwo.ca> wrote:
On 10/22/2006 3:56 PM, Deepayan Sarkar wrote:
Hi,
I have a package where I'm calling an R function (say "foo") from C
code. "foo" is in the same package, but is not exported. I construct
the call using lang1(install("foo")), but to eval it I need the
package's environment. Is there a way to do this? Passing the correct
environment through .Call() is not an option.
Right now, I'm getting the environment first using something like
rho = PROTECT(eval(lang2(install("environment"), install("bar")),
R_GlobalEnv))
where bar _is_ exported. However, this doesn't work if the package is
loaded but not attached, and is also risky because someone might
define another "bar" that is found first.
In R code, you could use getNamespace("pkg") to get the namespace
environment. I haven't tried this, but I'd assume
PROTECT(rho = eval(lang2(install("getNamespace"),
ScalarString(mkChar("pkg"))));
(or something like it) would be the C equivalent.
mkString("pkg") is simpler than ScalarString(mkChar("pkg")).
Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
On Sun, 22 Oct 2006, Seth Falcon wrote:
Seth Falcon <sfalcon at fhcrc.org> writes:
Perhaps: R_FindNamespace(mkString(where))
Sorry, this won't help you for package-level code as this function is part of the internal use only API. It would be nice to have access to it or a similar function from C in package code.
Hmm, it is declared in Rinternals.h, which is the public header for manipulating R objects at C level. As such it is available to packages, but as it is not documented in 'Writing R Extensions' it is subject to change. R_FindNamespace is essentially the same code as Duncan M provided, so it is a pretty simple function. (It still contains a test that namespaces are supported, and that seems long overdue for removal.)
Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
As far as I can tell from the original post, Deepayan asked for a way to find a package's namespace environment (rather than the package environment, <namespace:foo> not <package:foo>), so the subject line is subject to misinterpretation.
On Mon, 23 Oct 2006, Prof Brian Ripley wrote:
On Sun, 22 Oct 2006, Seth Falcon wrote:
Seth Falcon <sfalcon at fhcrc.org> writes:
Perhaps: R_FindNamespace(mkString(where))
Sorry, this won't help you for package-level code as this function is part of the internal use only API. It would be nice to have access to it or a similar function from C in package code.
Hmm, it is declared in Rinternals.h, which is the public header for manipulating R objects at C level. As such it is available to packages, but as it is not documented in 'Writing R Extensions' it is subject to change. R_FindNamespace is essentially the same code as Duncan M provided, so it is a pretty simple function. (It still contains a test that namespaces are supported, and that seems long overdue for removal.)
I think Deepayan's original enquiry was about getting hold of a namespace
environment from within an already loaded namespace. That can be done
entirely at C level, as we don't have the complication of possibly loading
the namespace. Just
val = findVarInFrame(R_NamespaceRegistry, install("pkgname"));
does that job, with val == R_UnboundValue should the namespace not be
loaded. AFAICS, everything here is available to a package writer, and
this is equally undocumented.
Brian D. Ripley, ripley at stats.ox.ac.uk Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/ University of Oxford, Tel: +44 1865 272861 (self) 1 South Parks Road, +44 1865 272866 (PA) Oxford OX1 3TG, UK Fax: +44 1865 272595
On Mon, 23 Oct 2006, Prof Brian Ripley wrote:
On Sun, 22 Oct 2006, Seth Falcon wrote:
Seth Falcon <sfalcon at fhcrc.org> writes:
Perhaps: R_FindNamespace(mkString(where))
Sorry, this won't help you for package-level code as this function is part of the internal use only API. It would be nice to have access to it or a similar function from C in package code.
Hmm, it is declared in Rinternals.h, which is the public header for manipulating R objects at C level. As such it is available to packages, but as it is not documented in 'Writing R Extensions' it is subject to change. R_FindNamespace is essentially the same code as Duncan M provided, so it is a pretty simple function. (It still contains a test that namespaces are supported, and that seems long overdue for removal.)
Except for a small detail: the code in R_FindNamespace protects the expression before callign eval -- this is needed since eval does not. Best, luke
Luke Tierney
Chair, Statistics and Actuarial Science
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa Phone: 319-335-3386
Department of Statistics and Fax: 319-335-3017
Actuarial Science
241 Schaeffer Hall email: luke at stat.uiowa.edu
Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu
On Mon, 23 Oct 2006, Prof Brian Ripley wrote:
As far as I can tell from the original post, Deepayan asked for a way to find a package's namespace environment (rather than the package environment, <namespace:foo> not <package:foo>), so the subject line is subject to misinterpretation. On Mon, 23 Oct 2006, Prof Brian Ripley wrote:
On Sun, 22 Oct 2006, Seth Falcon wrote:
Seth Falcon <sfalcon at fhcrc.org> writes:
Perhaps: R_FindNamespace(mkString(where))
Sorry, this won't help you for package-level code as this function is part of the internal use only API. It would be nice to have access to it or a similar function from C in package code.
Hmm, it is declared in Rinternals.h, which is the public header for manipulating R objects at C level. As such it is available to packages, but as it is not documented in 'Writing R Extensions' it is subject to change. R_FindNamespace is essentially the same code as Duncan M provided, so it is a pretty simple function. (It still contains a test that namespaces are supported, and that seems long overdue for removal.)
I think Deepayan's original enquiry was about getting hold of a namespace
environment from within an already loaded namespace. That can be done
entirely at C level, as we don't have the complication of possibly loading
the namespace. Just
val = findVarInFrame(R_NamespaceRegistry, install("pkgname"));
does that job, with val == R_UnboundValue should the namespace not be
loaded. AFAICS, everything here is available to a package writer, and
this is equally undocumented.
This level of detail should remain undocumented as it might be useful to change the representation at some point. R_FindNamespace is a safer bet, and we probably should document it as officially available.. Best, luke
Luke Tierney
Chair, Statistics and Actuarial Science
Ralph E. Wareham Professor of Mathematical Sciences
University of Iowa Phone: 319-335-3386
Department of Statistics and Fax: 319-335-3017
Actuarial Science
241 Schaeffer Hall email: luke at stat.uiowa.edu
Iowa City, IA 52242 WWW: http://www.stat.uiowa.edu
On 10/23/06, Luke Tierney <luke at stat.uiowa.edu> wrote:
On Mon, 23 Oct 2006, Prof Brian Ripley wrote:
As far as I can tell from the original post, Deepayan asked for a way to find a package's namespace environment (rather than the package environment, <namespace:foo> not <package:foo>), so the subject line is subject to misinterpretation. On Mon, 23 Oct 2006, Prof Brian Ripley wrote:
On Sun, 22 Oct 2006, Seth Falcon wrote:
Seth Falcon <sfalcon at fhcrc.org> writes:
Perhaps: R_FindNamespace(mkString(where))
Sorry, this won't help you for package-level code as this function is part of the internal use only API. It would be nice to have access to it or a similar function from C in package code.
Hmm, it is declared in Rinternals.h, which is the public header for manipulating R objects at C level. As such it is available to packages, but as it is not documented in 'Writing R Extensions' it is subject to change. R_FindNamespace is essentially the same code as Duncan M provided, so it is a pretty simple function. (It still contains a test that namespaces are supported, and that seems long overdue for removal.)
I think Deepayan's original enquiry was about getting hold of a namespace
environment from within an already loaded namespace. That can be done
entirely at C level, as we don't have the complication of possibly loading
the namespace. Just
val = findVarInFrame(R_NamespaceRegistry, install("pkgname"));
does that job, with val == R_UnboundValue should the namespace not be
loaded. AFAICS, everything here is available to a package writer, and
this is equally undocumented.
This level of detail should remain undocumented as it might be useful to change the representation at some point. R_FindNamespace is a safer bet, and we probably should document it as officially available..
OK, so I'm now using
rho = PROTECT(R_FindNamespace(mkString("mypkg"))),
Thanks,
Deepayan