s-news
[Top] [All Lists]

Re: Issue calling a C dll from Splus 8.0

To: gatreacy@maths.tcd.ie
Subject: Re: Issue calling a C dll from Splus 8.0
From: Terry Therneau <therneau@mayo.edu>
Date: Wed, 13 Aug 2008 08:03:30 -0500 (CDT)
Cc: s-news@wubios.wustl.edu
Reply-to: Terry Therneau <therneau@mayo.edu>
  When the C code accesses memory that it does not own, one often gets the 
symptoms that you describe.  Finding these can be very difficult.  There are 
two 
tools that I start with.
  
  1. Replace your .C call with .Cdebug.  (This is a part of Splus).  Do this 
for 
a case that does not fail, but is large enough to be "close to" failure mode.  
This routines pads out all of the vectors passed to the C routine with zeros, 
then checks on return that none of these extra zeros have been perturbed.  If 
any have, this often gives a good pointer to what part of the C code is in 
error.  A common one is to have a "work" vector tha was not quite big enough.
  
  2. About 90% of the time the call above doesn't work.  If you have access to 
a 
good C debugger/memory-checker, replace your .C call with a call to the CC 
function, given below.  It creates a main routine which is almost all data 
statements, followed by a call to your C routine that has exactly the arguments 
that S will be calling it with.  Change any calls to the S memory routines (eg 
S_alloc) to the corresponding C ones (alloc), and link the routine to your dll 
outside of S.  Now you have a stand alone mainline, that can be run under your 
debugger environment; set it up for strict memory checking and go.
  
  3. In unix, I can run S through the memory checking debugger.  (The setup was 
compliments of Bill Dunlap).  I don't use Windows, however, and have no insight 
there.
  
        Terry Therneau
        
-----------------------

CC <- function(subroutine, ..., copy, NAOK = F)
{
        assign("file", paste("D", subroutine, ".c", sep = ""), frame = 1)
        assign("out", function(...)
        cat(..., file = file, append = T), frame = 1)
        put <- function(type, name, data)
        {
                out(paste(type, " ", name, "[]", sep = ""), "= {")
                out(data, sep = ",", fill = 60, labels = "\t")
                out("};\n\n")
        }
        unix(paste("rm -f", file))
        args <- list(...)
        index <- seq(along = args)
        n <- names(args)
        if(length(n) == 0)
                n <- rep("", length(args))
        if(length(n) > 0)
                n <- ifelse(n == "", paste("arg", index, sep = ""), n)
        for(i in index)
                switch(storage.mode(args[[i]]),
                        character = put("static char *", n[i], paste("\"",
                                args[[i]], "\"", sep = "")),
                        integer = put("static long", n[i], args[[i]]),
                        single = put("static float", n[i], args[[i]]),
                        double = put("static double", n[i], args[[i]]),
                        logical = put("static long", n[i], args[[i]]),
                        stop(paste("Unknown mode", m[i], "for argument", i)))
        out("main() {\n", subroutine, "(", paste(n, collapse = ", "), ");\n}\n",
                sep = "")
}


<Prev in Thread] Current Thread [Next in Thread>