I have a use case with tcltk-package where I need to repeatedly call Tcl/Tk
functions
very quickly. For such purpose, the standard R-interface turned out to be too
slow, and
better option has been to call package's C-function dotTcl directly from my own
C-code.
Before R 4.4.0 it was possible to use
getNativeSymbolInfo("dotTcl","tcltk")$address (or
R_FindSymbol("dotTcl","tcltk",NULL) in C) to get the function-pointer and then
call the
function directly, even though it has not been registered as C-callable for
other
packages.
With R 4.4.0 these methods are unable to find the symbol anymore (tested in
Linux).
I was not able to find what change has caused this new behaviour.
Taking a look at tcltk source code, it can be seen that the dotTcl is called
using
.External within tcltk-package and there is a registration done for it with
R_registerRoutines. An object of class NativeSymbolInfo has also been created
in the
tcltk namespace, and that can be accessed using tcltk:::.C_dotTcl.
However, the tcltk:::.C_dotTcl$address is an external pointer of a class
RegisteredNativeSymbol and not directly the function pointer to the actual
routine. The
problem is that there appears not to be any R-level function that would extract
the actual
function-pointer and that the C-interface for R_RegisteredNativeSymbol has been
defined
in the internal Rdynpriv.h header that is not included in the public API
headers.
The only way I was able to access the function directly was using the following
C-level
approach in which essential parts of the headers are copied from the Rdynpriv.h:
#include <R.h>
#include <Rinternals.h>
#include <R_ext/Rdynload.h>
typedef struct {
char *name;
DL_FUNC fun;
int numArgs;
R_NativePrimitiveArgType *types;
} Rf_DotCSymbol;
typedef Rf_DotCSymbol Rf_DotFortranSymbol;
typedef struct {
char *name;
DL_FUNC fun;
int numArgs;
} Rf_DotCallSymbol;
typedef Rf_DotCallSymbol Rf_DotExternalSymbol;
struct Rf_RegisteredNativeSymbol {
NativeSymbolType type;
union {
Rf_DotCSymbol *c;
Rf_DotCallSymbol *call;
Rf_DotFortranSymbol *fortran;
Rf_DotExternalSymbol *external;
} symbol;
};
SEXP(*direct_dotTcl)(SEXP) = NULL;
SEXP FindRegFunc(SEXP symbol) {
R_RegisteredNativeSymbol *tmp = NULL;
tmp = (R_RegisteredNativeSymbol *) R_ExternalPtrAddr(symbol);
if (tmp==NULL) return R_NilValue;
direct_dotTcl = (SEXP(*)(SEXP)) tmp->symbol.external->fun;
return R_NilValue;
}
Although that works for me, I'm aware that this kind of approach is certainly
not
recommmended for publicly available external packages. However, I couldn't find
any
other more legitimate way to access dotTcl function directly from my C-code in
R 4.4.0.
I have two questions:
Would it be possible to get dotTcl C-function (in tcltk.c) of the tcltk-package
registered as C-callable from other packages?
Was it an intentional change that caused the hiding of the earlier visible
(registered)
symbols from other packages?
______________________________________________
[email protected] mailing list
https://stat.ethz.ch/mailman/listinfo/r-devel