Simon, Thank you for the prompt and comprehensive explaination. Using the explicit array casts for types and style in all the variants previously mentioned works fine - no errors, warnings, segfaults. Great! I suggest to add the "(R_NativePrimitiveArgType[4])" expression to the example in the manual.
Regards, - Daniel On Feb 6, 2012, at 3:47 PM, Simon Urbanek wrote: > Daniel, > > the code you are using is probably not what you intended - since there is no > length information the compiler assumes you are filling the structure > sequentially and thus the expected value is that for > R_NativePrimitiveArgType* which has no length, so it can only be initialized > with a scalar value, so you are setting > > R_NativePrimitiveArgType* types = REALSXP > > which is wrong as you are casing an integer into a pointer. Also that's why > you get the warnings which are all valid: > > ra.c:9: warning: braces around scalar initializer > -- because it is interpeted as {REALSXP} hence superfluous braces > > ra.c:9: warning: initialization makes pointer from integer without a cast > -- because you're initializing R_NativePrimitiveArgType* with an integer > (REALSXP) > > ra.c:9: warning: excess elements in scalar initializer > -- because INTSXP, ... must be ignored since "types" can only be initialized > with a scalar (pointer) > > For what you intended, you're using variable-length array so you have to > specify its length: > > {"myC", (DL_FUNC) &myC, 4, (R_NativePrimitiveArgType[4]) {REALSXP, INTSXP, > STRSXP, LGLSXP}} > > which will allocate extra static object (it has to because "types" is a > pointer, not a fixed array) - so the effect is the same as using a static > object. > > Cheers, > Simon > > > > On Feb 6, 2012, at 8:27 AM, Daniel Adler wrote: > >> Dear R List, >> >> I encountered a serious problem regarding the registration of ".C" when >> following the documentation "Writing R Extensions" >> that leads to a segmentation fault (tested on windows and mac os x). >> >> The registration mechanism for ".C" routines via R_registerRoutines and >> the R_CMethodDef structure has been enhanced recently with the >> addition of two fields, one for type specification and the other for >> the style (in, out, inout or irrelevant). >> >> According to the manual 'Writing R Extensions' of version 2.14.1 >> an example is given that specifies to use the fourth field (type information) >> for definitions of C routines that use the ".C" calling convention: >> >> R_CMethodDef cMethods[] = { >> {"myC", (DL_FUNC) &myC, 4, {REALSXP, INTSXP, STRSXP, LGLSXP}}, /* >> segfault! */ >> {NULL, NULL, 0} >> }; >> >> If I follow this example I get compiler warnings or errors (whether I use C >> or C++, respectively) and >> a segmentation fault (in the case of C) when doing R CMD INSTALL, which seem >> to happen during testing. >> See build log at the end of this e-mail. >> >> When removing the last field in the initializer list in order to register .C >> routines in the old way the segfault goes away: >> >> R_CMethodDef cMethods[] = { >> {"myC", (DL_FUNC) &myC, 4}, /* works */ >> {NULL, NULL, 0} >> }; >> >> There are still warnings/segfault or an error when initializing the >> undocumented fifth entry (parameter passing style), e.g. >> >> R_CMethodDef cMethods[] = { >> {"myC", (DL_FUNC) &myC, 4, {REALSXP, INTSXP, STRSXP, LGLSXP}, >> {R_ARG_IN, R_ARG_IN, R_ARG_IN, R_ARG_IN}, /* segfault! */ >> {NULL, NULL, 0} >> }; >> >> Using a C source, the warnings are: >> >> *** arch - i386 >> gcc -arch i386 -std=gnu99 >> -I/Library/Frameworks/R.framework/Resources/include >> -I/Library/Frameworks/R.framework/Resources/include/i386 >> -I/usr/local/include -fPIC -g -O2 -Wall -pedantic -c reg.c -o reg.o >> reg.c:24: warning: braces around scalar initializer >> reg.c:24: warning: (near initialization for ‘cMethods[0].types’) >> reg.c:24: warning: initialization makes pointer from integer without a cast >> reg.c:24: warning: excess elements in scalar initializer >> reg.c:24: warning: (near initialization for ‘cMethods[0].types’) >> reg.c:24: warning: excess elements in scalar initializer >> reg.c:24: warning: (near initialization for ‘cMethods[0].types’) >> reg.c:24: warning: excess elements in scalar initializer >> reg.c:24: warning: (near initialization for ‘cMethods[0].types’) >> >> >> Using C++, protecting the init/unload function prototypes and structure >> declarations via 'extern "C" { }', I get the following error: >> >> *** arch - i386 >> g++ -arch i386 -I/Library/Frameworks/R.framework/Resources/include >> -I/Library/Frameworks/R.framework/Resources/include/i386 >> -I/usr/local/include -fPIC -g -O2 -c reg.cpp -o reg.o >> reg.cpp:30: error: braces around scalar initializer for type >> ‚ÄòR_NativePrimitiveArgType*‚Äô >> >> (line 24 is the point on the entry, while line 30 is the end of the overall >> array initialization list in C++). >> >> If I put the type and style (unsigned int and enum) arrays separately, >> the build process works just fine. E.g. >> >> R_NativePrimitiveArgType types[] = {REALSXP, INTSXP, STRSXP, LGLSXP}; >> R_NativeArgStyle styles[] = { R_ARG_IN, R_ARG_IN, R_ARG_IN, R_ARG_IN }; >> >> R_CMethodDef cMethods[] = { >> {"myC", (DL_FUNC) &myC, 4, types, NULL}, /* works */ >> {"myC2", (DL_FUNC) &myC, 4, types, style}, /* works */ >> {NULL, NULL, 0} >> }; >> >> (Though I haven't tested the runtime behaviour yet.. but at least no >> segfault during R CMD INSTALL..) >> >> I wonder what is wrong with the static initializer lists?! >> >> I could imagine it has something to do with the standard compilance of the >> C/C++ >> compiler (due to the different behaviour warning or error during >> compilation). >> >> Anyway, going with the manual right now, the ordinary user will get warnings >> and >> errors - at least on the systems that I have tested (recent version of >> Rtools/Windows 7 >> and Mac OS X 10.6 with gcc 4.2.1). >> On Windows instead of a trace output, a window pops up during install to >> tell >> about a process crash. >> >> - Daniel >> >> PS: If it helps, I could put up a test package online for further debugging. >> >> --- build log: >> ---------------------------------------------------------------- >> >> ** testing if installed package can be loaded >> *** arch - i386 >> >> *** caught bus error *** >> address 0xe, cause 'non-existent physical address' >> >> Traceback: >> 1: dyn.load(file, DLLpath = DLLpath, ...) >> 2: library.dynam(lib, package, package.lib) >> 3: loadNamespace(package, c(which.lib.loc, lib.loc)) >> 4: doTryCatch(return(expr), name, parentenv, handler) >> 5: tryCatchOne(expr, names, parentenv, handlers[[1L]]) >> 6: tryCatchList(expr, classes, parentenv, handlers) >> 7: tryCatch(expr, error = function(e) { call <- conditionCall(e) if >> (!is.null(call)) { if (identical(call[[1L]], quote(doTryCatch))) >> call <- sys.call(-4L) dcall <- deparse(call)[1L] prefix >> <- paste("Error in", dcall, ": ") LONG <- 75L msg <- >> conditionMessage(e) sm <- strsplit(msg, "\n")[[1L]] w <- 14L + >> nchar(dcall, type = "w") + nchar(sm[1L], type = "w") if (is.na(w)) >> w <- 14L + nchar(dcall, type = "b") + nchar(sm[1L], >> type = "b") if (w > LONG) prefix <- paste(prefix, "\n ", >> sep = "") } else prefix <- "Error : " msg <- paste(prefix, >> conditionMessage(e), "\n", sep = "") .Internal(seterrmessage(msg[1L])) >> if (!silent && identical(getOption("show.error.messages"), TRUE)) { >> cat(msg, file = stderr()) .Internal(printDeferredWarnings()) >> } invisible(structure(msg, class = "try-error", condition = e))}) >> 8: try({ ns <- loadNamespace(package, c(which.lib.loc, lib.loc)) >> dataPath <- file.path(which.lib.loc, package, "data") env <- >> attachNamespace(ns, pos = pos, dataPath = dataPath, deps)}) >> 9: library(pkg_name, lib.loc = lib, character.only = TRUE, logical.return = >> TRUE) >> 10: withCallingHandlers(expr, packageStartupMessage = function(c) >> invokeRestart("muffleMessage")) >> 11: suppressPackageStartupMessages(library(pkg_name, lib.loc = lib, >> character.only = TRUE, logical.return = TRUE)) >> 12: doTryCatch(return(expr), name, parentenv, handler) >> 13: tryCatchOne(expr, names, parentenv, handlers[[1L]]) >> 14: tryCatchList(expr, classes, parentenv, handlers) >> 15: tryCatch(expr, error = function(e) { call <- conditionCall(e) if >> (!is.null(call)) { if (identical(call[[1L]], quote(doTryCatch))) >> call <- sys.call(-4L) dcall <- deparse(call)[1L] prefix >> <- paste("Error in", dcall, ": ") LONG <- 75L msg <- >> conditionMessage(e) sm <- strsplit(msg, "\n")[[1L]] w <- 14L + >> nchar(dcall, type = "w") + nchar(sm[1L], type = "w") if (is.na(w)) >> w <- 14L + nchar(dcall, type = "b") + nchar(sm[1L], >> type = "b") if (w > LONG) prefix <- paste(prefix, "\n ", >> sep = "") } else prefix <- "Error : " msg <- paste(prefix, >> conditionMessage(e), "\n", sep = "") .Internal(seterrmessage(msg[1L])) >> if (!silent && identical(getOption("show.error.messages"), TRUE)) { >> cat(msg, file = stderr()) .Internal(printDeferredWarnings()) >> } invisible(structure(msg, class = "try-error", condition = e))}) >> 16: try(suppressPackageStartupMessages(library(pkg_name, lib.loc = lib, >> character.only = TRUE, logical.return = TRUE))) >> 17: tools:::.test_load_package("mylib", >> "/Users/dadler/Library/R/2.14/library") >> aborting ... >> sh: line 1: 75200 Bus error >> '/Library/Frameworks/R.framework/Resources/bin/R' --arch=i386 --no-save >> --slave < >> /var/folders/Lr/Lrh7GWILEqCwHkyF1MdauE+++TI/-Tmp-//RtmpDqusSN/file1259d93ec2eb >> *** arch - x86_64 >> >> ______________________________________________ >> 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