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? ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel