The R Project SVN R

Rev

Rev 31319 | Rev 31593 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 31319 Rev 31591
Line 59... Line 59...
59
/* This looks up entry points in DLLs in a platform specific way. */
59
/* This looks up entry points in DLLs in a platform specific way. */
60
#include <Rdynpriv.h>
60
#include <Rdynpriv.h>
61
 
61
 
62
#define MAX_ARGS 65
62
#define MAX_ARGS 65
63
 
63
 
-
 
64
static DL_FUNC
64
static DL_FUNC R_FindNativeSymbolFromDLL(char *name, DllReference *dll, R_RegisteredNativeSymbol *symbol);
65
R_FindNativeSymbolFromDLL(char *name, DllReference *dll,
-
 
66
			  R_RegisteredNativeSymbol *symbol);
65
 
67
 
66
static SEXP naokfind(SEXP args, int * len, int *naok, int *dup, DllReference *dll);
68
static SEXP naokfind(SEXP args, int * len, int *naok, int *dup,
-
 
69
		     DllReference *dll);
67
static SEXP pkgtrim(SEXP args, DllReference *dll);
70
static SEXP pkgtrim(SEXP args, DllReference *dll);
68
 
71
 
69
/*
72
/*
70
  Checks whether the specified object correctly identifies a native routine.
73
  Checks whether the specified object correctly identifies a native routine.
71
  This can be  
74
  This can be
72
   a) a string,
75
   a) a string,
73
   b) an external pointer giving the address of the routine (e.g. getNativeSymbolInfo("foo")$address)
76
   b) an external pointer giving the address of the routine
-
 
77
      (e.g. getNativeSymbolInfo("foo")$address)
74
   c) or a NativeSymbolInfo itself  (e.g. getNativeSymbolInfo("foo"))
78
   c) or a NativeSymbolInfo itself  (e.g. getNativeSymbolInfo("foo"))
75
 */
79
 */
76
static int
80
static int
77
checkValidSymbolId(SEXP op, SEXP call, DL_FUNC *fun)
81
checkValidSymbolId(SEXP op, SEXP call, DL_FUNC *fun)
78
{
82
{
79
    if (isValidString(op))
83
    if (isValidString(op))
80
	return(0);
84
	return(0);
81
 
85
 
82
    else if((TYPEOF(op) == EXTPTRSXP && R_ExternalPtrTag(op) == Rf_install("native symbol"))) {
86
    else if((TYPEOF(op) == EXTPTRSXP && R_ExternalPtrTag(op) == Rf_install("native symbol"))) {
83
 
87
 
84
	if((*fun = R_ExternalPtrAddr(op)) == NULL) 
88
	if((*fun = R_ExternalPtrAddr(op)) == NULL)
85
	    errorcall(call, "NULL value passed as symbol address.");
89
	    errorcall(call, "NULL value passed as symbol address.");
86
	return(0);
90
	return(0);
87
 
91
 
88
    } else if(inherits(op, "NativeSymbolInfo")) {
92
    } else if(inherits(op, "NativeSymbolInfo")) {
89
 
93
 
Line 95... Line 99...
95
    return(0);
99
    return(0);
96
}
100
}
97
 
101
 
98
 
102
 
99
/*
103
/*
100
  This is the routine that is called by do_dotCode, do_dotcall and do_External
104
  This is the routine that is called by do_dotCode, do_dotcall and
101
  to find the DL_FUNC to invoke. It handles processing the arguments for the
105
  do_External to find the DL_FUNC to invoke. It handles processing the
102
  PACKAGE argument, if present, and also takes care of the cases where we are given
106
  arguments for the PACKAGE argument, if present, and also takes care
-
 
107
  of the cases where we are given a NativeSymbolInfo object, an
103
  a NativeSymbolInfo object, an address directly, and if the DLL is specified.
108
  address directly, and if the DLL is specified. If no PACKAGE is
104
  If no PACKAGE is provided, we check whether the calling function is in a namespace
109
  provided, we check whether the calling function is in a namespace
105
  and look there.
110
  and look there.
106
*/
111
*/
107
SEXP
112
SEXP
-
 
113
resolveNativeRoutine(SEXP args, DL_FUNC *fun,
108
resolveNativeRoutine(SEXP args, DL_FUNC *fun, R_RegisteredNativeSymbol *symbol, char *buf, 
114
		     R_RegisteredNativeSymbol *symbol, char *buf,
109
		     int *nargs, int *naok, int *dup, SEXP call)
115
		     int *nargs, int *naok, int *dup, SEXP call)
110
{
116
{
111
    SEXP op;
117
    SEXP op;
112
    char *p, *q;
118
    char *p, *q;
113
    DllReference dll = {"", NULL, NULL, NOT_DEFINED}; 
119
    DllReference dll = {"", NULL, NULL, NOT_DEFINED};
114
 
120
 
115
    op = CAR(args);
121
    op = CAR(args);
116
    checkValidSymbolId(op, call, fun);
122
    checkValidSymbolId(op, call, fun);
117
 
123
 
118
    /* The following code modifies the argument list */
124
    /* The following code modifies the argument list */
Line 120... Line 126...
120
    /* with its arguments evaluated. */
126
    /* with its arguments evaluated. */
121
 
127
 
122
    strcpy(dll.DLLname, "");
128
    strcpy(dll.DLLname, "");
123
    if(symbol->type == R_C_SYM || symbol->type == R_FORTRAN_SYM) {
129
    if(symbol->type == R_C_SYM || symbol->type == R_FORTRAN_SYM) {
124
	args = naokfind(CDR(args), nargs, naok, dup, &dll);
130
	args = naokfind(CDR(args), nargs, naok, dup, &dll);
125
	
131
 
126
	if(*naok == NA_LOGICAL)
132
	if(*naok == NA_LOGICAL)
127
	    errorcall(call, "invalid naok value");
133
	    errorcall(call, "invalid naok value");
128
	if(*nargs > MAX_ARGS)
134
	if(*nargs > MAX_ARGS)
129
	    errorcall(call, "too many arguments in foreign function call");
135
	    errorcall(call, "too many arguments in foreign function call");
130
    } else {
136
    } else {
Line 139... Line 145...
139
	q = buf;
145
	q = buf;
140
	while ((*q = *p) != '\0') {
146
	while ((*q = *p) != '\0') {
141
	    p++;
147
	    p++;
142
	    q++;
148
	    q++;
143
	}
149
	}
144
    } 
150
    }
145
 
151
 
146
    if(!*fun) {
152
    if(!*fun) {
147
	if(dll.type != FILENAME) {
153
	if(dll.type != FILENAME) {
148
	    *fun = R_FindNativeSymbolFromDLL(buf, &dll, symbol);
154
	    *fun = R_FindNativeSymbolFromDLL(buf, &dll, symbol);
149
	    if(!fun) {
155
	    if(!fun) {
150
		errorcall(call, "cannot resolve native routine");
156
		errorcall(call, "cannot resolve native routine");
151
	    }
157
	    }
152
	} 
158
	}
153
 
159
 
154
	if (!*fun && !(*fun = R_FindSymbol(buf, dll.DLLname, symbol))) {
160
	if (!*fun && !(*fun = R_FindSymbol(buf, dll.DLLname, symbol))) {
155
	    if(strlen(dll.DLLname))
161
	    if(strlen(dll.DLLname))
156
		errorcall(call, "%s function name not in DLL for package %s",
162
		errorcall(call, "%s function name not in DLL for package %s",
157
			   symbol->type == R_FORTRAN_SYM ? "Fortran" : "C", 
163
			   symbol->type == R_FORTRAN_SYM ? "Fortran" : "C",
158
			   dll.DLLname);
164
			   dll.DLLname);
159
	    else
165
	    else
160
		errorcall(call, "%s function name not in load table",
166
		errorcall(call, "%s function name not in load table",
161
			  symbol->type == R_FORTRAN_SYM ? "Fortran" : "C"); 
167
			  symbol->type == R_FORTRAN_SYM ? "Fortran" : "C");
162
	}
168
	}
163
    }
169
    }
164
 
170
 
165
    return(args);
171
    return(args);
166
}
172
}
Line 185... Line 191...
185
  return(TRUE);
191
  return(TRUE);
186
}
192
}
187
 
193
 
188
 
194
 
189
 
195
 
190
static void *RObjToCPtr(SEXP s, int naok, int dup, int narg, int Fort, const char *name, R_toCConverter **converter,
196
static void *RObjToCPtr(SEXP s, int naok, int dup, int narg, int Fort,
-
 
197
			const char *name, R_toCConverter **converter,
191
                          int targetType)
198
			int targetType)
192
{
199
{
193
    int *iptr;
200
    int *iptr;
194
    float *sptr;
201
    float *sptr;
195
    double *rptr;
202
    double *rptr;
196
    char **cptr, *fptr;
203
    char **cptr, *fptr;
Line 268... Line 275...
268
    case CPLXSXP:
275
    case CPLXSXP:
269
	n = LENGTH(s);
276
	n = LENGTH(s);
270
	zptr = COMPLEX(s);
277
	zptr = COMPLEX(s);
271
	for (i = 0 ; i < n ; i++) {
278
	for (i = 0 ; i < n ; i++) {
272
	    if(!naok && (!R_FINITE(zptr[i].r) || !R_FINITE(zptr[i].i)))
279
	    if(!naok && (!R_FINITE(zptr[i].r) || !R_FINITE(zptr[i].i)))
273
		error("Complex NA/NaN/Inf in foreign function call (arg %d)", narg);
280
		error("Complex NA/NaN/Inf in foreign function call (arg %d)",
-
 
281
		      narg);
274
	}
282
	}
275
	if (dup) {
283
	if (dup) {
276
	    zptr = (Rcomplex*)R_alloc(n, sizeof(Rcomplex));
284
	    zptr = (Rcomplex*)R_alloc(n, sizeof(Rcomplex));
277
	    for (i = 0 ; i < n ; i++)
285
	    for (i = 0 ; i < n ; i++)
278
		zptr[i] = COMPLEX(s)[i];
286
		zptr[i] = COMPLEX(s)[i];
Line 282... Line 290...
282
    case STRSXP:
290
    case STRSXP:
283
	if(!dup)
291
	if(!dup)
284
	    error("character variables must be duplicated in .C/.Fortran");
292
	    error("character variables must be duplicated in .C/.Fortran");
285
	n = LENGTH(s);
293
	n = LENGTH(s);
286
	if(Fort) {
294
	if(Fort) {
-
 
295
	    if(n > 1)
287
	    if(n > 1) warning("only first string in char vector used in .Fortran");
296
		warning("only first string in char vector used in .Fortran");
288
	    l = strlen(CHAR(STRING_ELT(s, 0)));
297
	    l = strlen(CHAR(STRING_ELT(s, 0)));
289
	    fptr = (char*)R_alloc(max(255, l) + 1, sizeof(char));
298
	    fptr = (char*)R_alloc(max(255, l) + 1, sizeof(char));
290
	    strcpy(fptr, CHAR(STRING_ELT(s, 0)));
299
	    strcpy(fptr, CHAR(STRING_ELT(s, 0)));
291
	    return (void*)fptr;
300
	    return (void*)fptr;
292
	} else {
301
	} else {
Line 325... Line 334...
325
	return (void*)s;
334
	return (void*)s;
326
    }
335
    }
327
}
336
}
328
 
337
 
329
 
338
 
330
static SEXP CPtrToRObj(void *p, SEXP arg, int Fort, R_NativePrimitiveArgType type)
339
static SEXP CPtrToRObj(void *p, SEXP arg, int Fort,
-
 
340
		       R_NativePrimitiveArgType type)
331
{
341
{
332
    int *iptr, n=length(arg);
342
    int *iptr, n=length(arg);
333
    float *sptr;
343
    float *sptr;
334
    double *rptr;
344
    double *rptr;
335
    char **cptr, buf[256];
345
    char **cptr, buf[256];
Line 424... Line 434...
424
/* or Fortran code which is either statically or dynamically linked. */
434
/* or Fortran code which is either statically or dynamically linked. */
425
 
435
 
426
/* NB: despite its name, this leaves NAOK and DUP arguments on the list */
436
/* NB: despite its name, this leaves NAOK and DUP arguments on the list */
427
 
437
 
428
/* find NAOK and DUP, find and remove PACKAGE */
438
/* find NAOK and DUP, find and remove PACKAGE */
429
static SEXP naokfind(SEXP args, int * len, int *naok, int *dup, DllReference *dll)
439
static SEXP naokfind(SEXP args, int * len, int *naok, int *dup,
-
 
440
		     DllReference *dll)
430
{
441
{
431
    SEXP s, prev;
442
    SEXP s, prev;
432
    int nargs=0, naokused=0, dupused=0, pkgused=0;
443
    int nargs=0, naokused=0, dupused=0, pkgused=0;
433
    char *p;
444
    char *p;
434
 
445
 
Line 463... Line 474...
463
		    dll->dll = (HINSTANCE) R_ExternalPtrAddr(CAR(s));
474
		    dll->dll = (HINSTANCE) R_ExternalPtrAddr(CAR(s));
464
		    dll->type = DLL_HANDLE;
475
		    dll->type = DLL_HANDLE;
465
		} else if(TYPEOF(CAR(s)) == VECSXP) {
476
		} else if(TYPEOF(CAR(s)) == VECSXP) {
466
		    dll->type = R_OBJECT;
477
		    dll->type = R_OBJECT;
467
		    dll->obj = s;
478
		    dll->obj = s;
-
 
479
		    strcpy(dll->DLLname,
468
		    strcpy(dll->DLLname, CHAR(STRING_ELT(VECTOR_ELT(CAR(s), 1), 0)));
480
			   CHAR(STRING_ELT(VECTOR_ELT(CAR(s), 1), 0)));
469
		    dll->dll = (HINSTANCE) R_ExternalPtrAddr(VECTOR_ELT(s, 4));
481
		    dll->dll = (HINSTANCE) R_ExternalPtrAddr(VECTOR_ELT(s, 4));
470
		}
482
		}
471
	    }
483
	    }
472
	} else {
484
	} else {
473
	    nargs++;
485
	    nargs++;
Line 581... Line 593...
581
    R_RegisteredNativeSymbol symbol = {R_EXTERNAL_SYM, {NULL}, NULL};
593
    R_RegisteredNativeSymbol symbol = {R_EXTERNAL_SYM, {NULL}, NULL};
582
    /* I don't like this messing with vmax <TSL> */
594
    /* I don't like this messing with vmax <TSL> */
583
    /* But it is needed for clearing R_alloc and to be like .Call <BDR>*/
595
    /* But it is needed for clearing R_alloc and to be like .Call <BDR>*/
584
    char *vmax = vmaxget(), buf[128];
596
    char *vmax = vmaxget(), buf[128];
585
 
597
 
586
    args = resolveNativeRoutine(args, &fun, &symbol, buf, NULL, NULL, NULL, call);
598
    args = resolveNativeRoutine(args, &fun, &symbol, buf, NULL, NULL,
-
 
599
				NULL, call);
587
 
600
 
588
    /* Some external symbols that are registered may have 0 as the expected number of arguments.
601
    /* Some external symbols that are registered may have 0 as the
-
 
602
       expected number of arguments.  We may want a warning
589
       We may want a warning here. However, the number of values may vary across calls
603
       here. However, the number of values may vary across calls and
590
       and that is why people use the .External() mechanism.  So perhaps we should just kill this 
604
       that is why people use the .External() mechanism.  So perhaps
-
 
605
       we should just kill this check.
591
       check. */
606
    */
592
#ifdef CHECK_EXTERNAL_ARG_COUNT         /* Off by default. */
607
#ifdef CHECK_EXTERNAL_ARG_COUNT         /* Off by default. */
593
    if(symbol.symbol.external && symbol.symbol.external->numArgs > -1) {
608
    if(symbol.symbol.external && symbol.symbol.external->numArgs > -1) {
594
	if(symbol.symbol.external->numArgs != length(args))
609
	if(symbol.symbol.external->numArgs != length(args))
595
	    error("Incorrect number of arguments (%d), expecting %d for %s",
610
	    error("Incorrect number of arguments (%d), expecting %d for %s",
596
		  length(args), symbol.symbol.external->numArgs, CHAR(STRING_ELT(op, 0)));
611
		  length(args), symbol.symbol.external->numArgs,
-
 
612
		  CHAR(STRING_ELT(CAR(args), 0)));
597
    }
613
    }
598
#endif
614
#endif
599
 
615
 
600
    retval = (SEXP)fun(args);
616
    retval = (SEXP)fun(args);
601
    vmaxset(vmax);
617
    vmaxset(vmax);
Line 611... Line 627...
611
    R_RegisteredNativeSymbol symbol = {R_CALL_SYM, {NULL}, NULL};
627
    R_RegisteredNativeSymbol symbol = {R_CALL_SYM, {NULL}, NULL};
612
    int nargs;
628
    int nargs;
613
    char *vmax = vmaxget();
629
    char *vmax = vmaxget();
614
    char buf[128];
630
    char buf[128];
615
 
631
 
616
    op = CAR(args);
-
 
617
    args = resolveNativeRoutine(args, &fun, &symbol, buf, NULL, NULL, NULL, call);
632
    args = resolveNativeRoutine(args, &fun, &symbol, buf, NULL, NULL,
-
 
633
				NULL, call);
618
    args = CDR(args);
634
    args = CDR(args);
619
 
635
 
620
    for(nargs = 0, pargs = args ; pargs != R_NilValue; pargs = CDR(pargs)) {
636
    for(nargs = 0, pargs = args ; pargs != R_NilValue; pargs = CDR(pargs)) {
621
        if (nargs == MAX_ARGS)
637
        if (nargs == MAX_ARGS)
622
            errorcall(call, "too many arguments in foreign function call");
638
            errorcall(call, "too many arguments in foreign function call");
Line 624... Line 640...
624
	nargs++;
640
	nargs++;
625
    }
641
    }
626
    if(symbol.symbol.call && symbol.symbol.call->numArgs > -1) {
642
    if(symbol.symbol.call && symbol.symbol.call->numArgs > -1) {
627
	if(symbol.symbol.call->numArgs != nargs)
643
	if(symbol.symbol.call->numArgs != nargs)
628
	    error("Incorrect number of arguments (%d), expecting %d for %s",
644
	    error("Incorrect number of arguments (%d), expecting %d for %s",
629
		  nargs, symbol.symbol.call->numArgs, CHAR(STRING_ELT(op, 0)));
645
		  nargs, symbol.symbol.call->numArgs,
-
 
646
		  CHAR(STRING_ELT(CAR(args), 0)));
630
    }
647
    }
631
 
648
 
632
    retval = R_NilValue;	/* -Wall */
649
    retval = R_NilValue;	/* -Wall */
633
    switch (nargs) {
650
    switch (nargs) {
634
    case 0:
651
    case 0:
Line 1334... Line 1351...
1334
 
1351
 
1335
 
1352
 
1336
/*
1353
/*
1337
  We are given the PACKAGE argument in dll.obj
1354
  We are given the PACKAGE argument in dll.obj
1338
  and we can try to figure out how to resolve this.
1355
  and we can try to figure out how to resolve this.
1339
  0) dll.obj is NULL.  Then find the environment of the 
1356
  0) dll.obj is NULL.  Then find the environment of the
1340
   calling function and if it is a namespace, get the 
1357
   calling function and if it is a namespace, get the
1341
   
1358
 
1342
  1) dll.obj is a DLLInfo object
1359
  1) dll.obj is a DLLInfo object
1343
*/
1360
*/
1344
static DL_FUNC
1361
static DL_FUNC
1345
R_FindNativeSymbolFromDLL(char *name, DllReference *dll, R_RegisteredNativeSymbol *symbol)
1362
R_FindNativeSymbolFromDLL(char *name, DllReference *dll,
-
 
1363
			  R_RegisteredNativeSymbol *symbol)
1346
{
1364
{
1347
    int numProtects = 0;
1365
    int numProtects = 0;
1348
    DllInfo *info;
1366
    DllInfo *info;
1349
    DL_FUNC fun = NULL;
1367
    DL_FUNC fun = NULL;
1350
 
1368
 
Line 1354... Line 1372...
1354
    }
1372
    }
1355
 
1373
 
1356
    if(inherits(dll->obj, "DLLInfo")) {
1374
    if(inherits(dll->obj, "DLLInfo")) {
1357
	SEXP tmp;
1375
	SEXP tmp;
1358
/*XXX*/
1376
/*XXX*/
1359
DL_FUNC R_dlsym(DllInfo *info, char const *name, R_RegisteredNativeSymbol *symbol);
1377
DL_FUNC R_dlsym(DllInfo *info, char const *name,
-
 
1378
		R_RegisteredNativeSymbol *symbol);
1360
	tmp = VECTOR_ELT(dll->obj, 4);
1379
	tmp = VECTOR_ELT(dll->obj, 4);
1361
	info = (DllInfo *) R_ExternalPtrAddr(tmp);
1380
	info = (DllInfo *) R_ExternalPtrAddr(tmp);
1362
	if(!info) 
1381
	if(!info)
1363
	    error("NULL value for DLLInfoReference when looking for DLL");
1382
	    error("NULL value for DLLInfoReference when looking for DLL");
1364
	fun = R_dlsym(info, name, symbol);
1383
	fun = R_dlsym(info, name, symbol);
1365
    }
1384
    }
1366
 
1385
 
1367
    if(numProtects)
1386
    if(numProtects)
Line 1377... Line 1396...
1377
{
1396
{
1378
    void **cargs;
1397
    void **cargs;
1379
    int dup, havenames, naok, nargs, which;
1398
    int dup, havenames, naok, nargs, which;
1380
    DL_FUNC fun = NULL;
1399
    DL_FUNC fun = NULL;
1381
    SEXP ans, pargs, s;
1400
    SEXP ans, pargs, s;
1382
    R_toCConverter  *argConverters[65]; /* the post-call converters back to R objects. */
1401
    /* the post-call converters back to R objects. */
-
 
1402
    R_toCConverter  *argConverters[65];
1383
    R_RegisteredNativeSymbol symbol = {R_C_SYM, {NULL}, NULL};
1403
    R_RegisteredNativeSymbol symbol = {R_C_SYM, {NULL}, NULL};
1384
    R_NativePrimitiveArgType *checkTypes = NULL;
1404
    R_NativePrimitiveArgType *checkTypes = NULL;
1385
    R_NativeArgStyle *argStyles = NULL;
1405
    R_NativeArgStyle *argStyles = NULL;
1386
    char *vmax, symName[128];
1406
    char *vmax, symName[128];
1387
 
1407
 
Line 1393... Line 1413...
1393
    vmax = vmaxget();
1413
    vmax = vmaxget();
1394
    which = PRIMVAL(op);
1414
    which = PRIMVAL(op);
1395
    if(which)
1415
    if(which)
1396
	symbol.type = R_FORTRAN_SYM;
1416
	symbol.type = R_FORTRAN_SYM;
1397
 
1417
 
1398
    args = resolveNativeRoutine(args, &fun, &symbol, symName, &nargs, &naok, &dup, call);
1418
    args = resolveNativeRoutine(args, &fun, &symbol, symName, &nargs,
-
 
1419
				&naok, &dup, call);
1399
 
1420
 
1400
    if(symbol.symbol.c && symbol.symbol.c->numArgs > -1) {
1421
    if(symbol.symbol.c && symbol.symbol.c->numArgs > -1) {
1401
	if(symbol.symbol.c->numArgs != nargs)
1422
	if(symbol.symbol.c->numArgs != nargs)
1402
	    error("Incorrect number of arguments (%d), expecting %d for %s",
1423
	    error("Incorrect number of arguments (%d), expecting %d for %s",
1403
		  nargs, symbol.symbol.c->numArgs, symName);
1424
		  nargs, symbol.symbol.c->numArgs, symName);
Line 1413... Line 1434...
1413
    /* once below on the way out. */
1434
    /* once below on the way out. */
1414
    cargs = (void**)R_alloc(nargs, sizeof(void*));
1435
    cargs = (void**)R_alloc(nargs, sizeof(void*));
1415
    nargs = 0;
1436
    nargs = 0;
1416
    for(pargs = args ; pargs != R_NilValue; pargs = CDR(pargs)) {
1437
    for(pargs = args ; pargs != R_NilValue; pargs = CDR(pargs)) {
1417
#ifdef THROW_REGISTRATION_TYPE_ERROR
1438
#ifdef THROW_REGISTRATION_TYPE_ERROR
-
 
1439
        if(checkTypes &&
1418
        if(checkTypes && !comparePrimitiveTypes(checkTypes[nargs], CAR(pargs), dup)) {
1440
	   !comparePrimitiveTypes(checkTypes[nargs], CAR(pargs), dup)) {
1419
            /* We can loop over all the arguments and report all the erroneous ones,
1441
            /* We can loop over all the arguments and report all the
1420
               but then we would also want to avoid the conversions.
1442
               erroneous ones, but then we would also want to avoid
-
 
1443
               the conversions.  Also, in the future, we may just
1421
               Also, in the future, we may just attempt to coerce the value
1444
               attempt to coerce the value to the appropriate
1422
               to the appropriate type. This is why we pass the checkTypes[nargs]
1445
               type. This is why we pass the checkTypes[nargs] value
1423
               value to RObjToCPtr(). We just have to sort out the ability to
1446
               to RObjToCPtr(). We just have to sort out the ability
1424
               return the correct value which is complicated by dup, etc. */
1447
               to return the correct value which is complicated by
-
 
1448
               dup, etc. */
1425
	    error("Wrong type for argument %d in call to %s", nargs+1, symName);
1449
	    error("Wrong type for argument %d in call to %s",
-
 
1450
		  nargs+1, symName);
1426
	}
1451
	}
1427
#endif
1452
#endif
1428
	cargs[nargs] = RObjToCPtr(CAR(pargs), naok, dup, nargs + 1,
1453
	cargs[nargs] = RObjToCPtr(CAR(pargs), naok, dup, nargs + 1,
1429
				  which, symName, argConverters + nargs,
1454
				  which, symName, argConverters + nargs,
1430
				  checkTypes ? checkTypes[nargs] : 0);
1455
				  checkTypes ? checkTypes[nargs] : 0);
Line 2040... Line 2065...
2040
	        PROTECT(s = R_NilValue);
2065
	        PROTECT(s = R_NilValue);
2041
	    } else if(argConverters[nargs]) {
2066
	    } else if(argConverters[nargs]) {
2042
                if(argConverters[nargs]->reverse) {
2067
                if(argConverters[nargs]->reverse) {
2043
		    info.argIndex = nargs;
2068
		    info.argIndex = nargs;
2044
		    s = argConverters[nargs]->reverse(cargs[nargs], CAR(pargs),
2069
		    s = argConverters[nargs]->reverse(cargs[nargs], CAR(pargs),
-
 
2070
						      &info,
2045
                                                       &info, argConverters[nargs]);
2071
						      argConverters[nargs]);
2046
		} else
2072
		} else
2047
		    s = R_NilValue;
2073
		    s = R_NilValue;
2048
		PROTECT(s);
2074
		PROTECT(s);
2049
	    } else {
2075
	    } else {
2050
		PROTECT(s = CPtrToRObj(cargs[nargs], CAR(pargs), which,
2076
		PROTECT(s = CPtrToRObj(cargs[nargs], CAR(pargs), which,
Line 2184... Line 2210...
2184
    case INTSXP:
2210
    case INTSXP:
2185
    case REALSXP:
2211
    case REALSXP:
2186
    case CPLXSXP:
2212
    case CPLXSXP:
2187
    case STRSXP:
2213
    case STRSXP:
2188
	if(nres > 0)
2214
	if(nres > 0)
2189
	    results[0] = RObjToCPtr(s, 1, 1, 0, 0, (const char *)NULL, NULL, 0);
2215
	    results[0] = RObjToCPtr(s, 1, 1, 0, 0, (const char *)NULL,
-
 
2216
				    NULL, 0);
2190
	break;
2217
	break;
2191
    case VECSXP:
2218
    case VECSXP:
2192
	n = length(s);
2219
	n = length(s);
2193
	if (nres < n) n = nres;
2220
	if (nres < n) n = nres;
2194
	for (i = 0 ; i < n ; i++) {
2221
	for (i = 0 ; i < n ; i++) {
2195
	    results[i] = RObjToCPtr(VECTOR_ELT(s, i), 1, 1, 0, 0, (const char *)NULL, NULL, 0);
2222
	    results[i] = RObjToCPtr(VECTOR_ELT(s, i), 1, 1, 0, 0,
-
 
2223
				    (const char *)NULL, NULL, 0);
2196
	}
2224
	}
2197
	break;
2225
	break;
2198
    case LISTSXP:
2226
    case LISTSXP:
2199
	n = length(s);
2227
	n = length(s);
2200
	if(nres < n) n = nres;
2228
	if(nres < n) n = nres;
2201
	for(i=0 ; i<n ; i++) {
2229
	for(i=0 ; i<n ; i++) {
2202
	    results[i] = RObjToCPtr(s, 1, 1, 0, 0, (const char *)NULL, NULL, 0);
2230
	    results[i] = RObjToCPtr(s, 1, 1, 0, 0, (const char *)NULL,
-
 
2231
				    NULL, 0);
2203
	    s = CDR(s);
2232
	    s = CDR(s);
2204
	}
2233
	}
2205
	break;
2234
	break;
2206
    }
2235
    }
2207
    UNPROTECT(2);
2236
    UNPROTECT(2);