comparison R/rdyncall/src/rdyncall.c @ 0:0cfcc391201f

initial from svn dyncall-1745
author Daniel Adler
date Thu, 19 Mar 2015 22:26:28 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:0cfcc391201f
1 /** ===========================================================================
2 ** R-Package: rdyncall
3 ** File: src/rdyncall.c
4 ** Description: R bindings to dyncall
5 **/
6
7 #include <Rinternals.h>
8 #include "dyncall.h"
9 #include "rdyncall_signature.h"
10 #include <string.h>
11 #include <ctype.h>
12
13 /** ---------------------------------------------------------------------------
14 ** C-Function: new_callvm
15 ** R-Interface: .Call
16 **/
17
18 SEXP r_new_callvm(SEXP mode_x, SEXP size_x)
19 {
20 /* default call mode is "cdecl" */
21 int size_i = INTEGER(size_x)[0];
22
23 const char* mode_S = CHAR( STRING_ELT( mode_x, 0 ) );
24
25 int mode_i = DC_CALL_C_DEFAULT;
26 if (strcmp(mode_S,"default") == 0 || strcmp(mode_S,"cdecl") == 0) mode_i = DC_CALL_C_DEFAULT;
27 #if WIN32
28 else if (strcmp(mode_S,"stdcall") == 0) mode_i = DC_CALL_C_X86_WIN32_STD;
29 else if (strcmp(mode_S,"thiscall") == 0) mode_i = DC_CALL_C_X86_WIN32_THIS_GNU;
30 else if (strcmp(mode_S,"thiscall.gcc") == 0) mode_i = DC_CALL_C_X86_WIN32_THIS_GNU;
31 else if (strcmp(mode_S,"thiscall.msvc") == 0) mode_i = DC_CALL_C_X86_WIN32_THIS_MS;
32 else if (strcmp(mode_S,"fastcall") == 0) mode_i = DC_CALL_C_X86_WIN32_FAST_GNU;
33 else if (strcmp(mode_S,"fastcall.msvc") == 0) mode_i = DC_CALL_C_X86_WIN32_FAST_MS;
34 else if (strcmp(mode_S,"fastcall.gcc") == 0) mode_i = DC_CALL_C_X86_WIN32_FAST_GNU;
35 #endif
36 /*
37 else { error("invalid 'callmode'"); return R_NilValue; }
38 */
39
40 DCCallVM* pvm = dcNewCallVM(size_i);
41 dcMode( pvm, mode_i );
42 return R_MakeExternalPtr( pvm, R_NilValue, R_NilValue );
43 }
44
45 /** ---------------------------------------------------------------------------
46 ** C-Function: free_callvm
47 ** R-Interface: .Call
48 **/
49
50 SEXP r_free_callvm(SEXP callvm_x)
51 {
52 DCCallVM* callvm_p = (DCCallVM*) R_ExternalPtrAddr( callvm_x );
53 dcFree( callvm_p );
54 return R_NilValue;
55 }
56
57 /** ---------------------------------------------------------------------------
58 ** C-Function: r_dyncall
59 ** R-Interface: .External
60 **/
61
62 SEXP r_dyncall(SEXP args) /* callvm, address, signature, args ... */
63 {
64 DCCallVM* pvm;
65 void* addr;
66 const char* signature;
67 const char* sig;
68 SEXP arg;
69 int ptrcnt;
70 int argpos;
71
72 args = CDR(args);
73
74 /* extract CallVM reference, address and signature */
75
76 pvm = (DCCallVM*) R_ExternalPtrAddr( CAR(args) ); args = CDR(args);
77
78 switch(TYPEOF(CAR(args))) {
79 case EXTPTRSXP:
80 addr = R_ExternalPtrAddr( CAR(args) ); args = CDR(args);
81 if (!addr) {
82 error("Target address is null-pointer.");
83 return R_NilValue; /* dummy */
84 }
85 break;
86 default:
87 error("Target address must be external pointer.");
88 return R_NilValue; /* dummy */
89 }
90 signature = CHAR( STRING_ELT( CAR(args), 0 ) ); args = CDR(args);
91 sig = signature;
92
93 if (!pvm) {
94 error("Argument 'callvm' is null");
95 /* dummy */ return R_NilValue;
96 }
97 if (!addr) {
98 error("Argument 'addr' is null");
99 /* dummy */ return R_NilValue;
100 }
101 /* reset CallVM to initial state */
102
103 dcReset(pvm);
104 ptrcnt = 0;
105 argpos = 0;
106
107 /* function calling convention prefix '_' */
108 if (*sig == DC_SIGCHAR_CC_PREFIX) {
109 /* specify calling convention by signature prefix hint */
110 ++sig;
111 char ch = *sig++;
112 int mode = DC_CALL_C_DEFAULT;
113 switch(ch)
114 {
115 case DC_SIGCHAR_CC_STDCALL:
116 mode = DC_CALL_C_X86_WIN32_STD; break;
117 case DC_SIGCHAR_CC_FASTCALL_GNU:
118 mode = DC_CALL_C_X86_WIN32_FAST_GNU; break;
119 case DC_SIGCHAR_CC_FASTCALL_MS:
120 mode = DC_CALL_C_X86_WIN32_FAST_MS; break;
121 default:
122 error("Unknown calling convention prefix hint signature character '%c'", ch );
123 /* dummy */ return R_NilValue;
124 }
125 dcMode(pvm, mode);
126 }
127
128 /* load arguments */
129 for(;;) {
130
131 char ch = *sig++;
132
133 if (ch == '\0') {
134 error("Function-call signature '%s' is invalid - missing argument terminator character ')' and return type signature.", signature);
135 /* dummy */ return R_NilValue;
136 }
137 /* argument terminator */
138 if (ch == ')') break;
139
140 /* end of arguments? */
141 if (args == R_NilValue) {
142 error("Not enough arguments for function-call signature '%s'.", signature);
143 /* dummy */ return R_NilValue;
144 }
145 /* pointer counter */
146 else if (ch == '*') { ptrcnt++; continue; }
147
148 /* unpack next argument */
149 arg = CAR(args); args = CDR(args);
150 argpos++;
151
152 int type_id = TYPEOF(arg);
153
154 if (ptrcnt == 0) { /* base types */
155
156 /* 'x' signature for passing language objects 'as-is' */
157 if (ch == DC_SIGCHAR_SEXP) {
158 dcArgPointer(pvm, (void*)arg);
159 continue;
160 }
161
162 if ( type_id != NILSXP && type_id != EXTPTRSXP && LENGTH(arg) == 0 ) {
163 error("Argument type mismatch at position %d: expected length greater zero.", argpos);
164 /* dummy */ return R_NilValue;
165 }
166 switch(ch) {
167 case DC_SIGCHAR_BOOL:
168 {
169 DCbool boolValue;
170 switch(type_id)
171 {
172 case LGLSXP: boolValue = ( LOGICAL(arg)[0] == 0 ) ? DC_FALSE : DC_TRUE; break;
173 case INTSXP: boolValue = ( INTEGER(arg)[0] == 0 ) ? DC_FALSE : DC_TRUE; break;
174 case REALSXP: boolValue = ( REAL(arg)[0] == 0.0 ) ? DC_FALSE : DC_TRUE; break;
175 case RAWSXP: boolValue = ( RAW(arg)[0] == 0 ) ? DC_FALSE : DC_TRUE; break;
176 default: error("Argument type mismatch at position %d: expected C bool convertable value", argpos); /* dummy */ return R_NilValue;
177 }
178 dcArgBool(pvm, boolValue );
179 }
180 break;
181 case DC_SIGCHAR_CHAR:
182 {
183 char charValue;
184 switch(type_id)
185 {
186 case LGLSXP: charValue = (char) LOGICAL(arg)[0]; break;
187 case INTSXP: charValue = (char) INTEGER(arg)[0]; break;
188 case REALSXP: charValue = (char) REAL(arg)[0]; break;
189 case RAWSXP: charValue = (char) RAW(arg)[0]; break;
190 default: error("Argument type mismatch at position %d: expected C char convertable value", argpos); /* dummy */ return R_NilValue;
191 }
192 dcArgChar(pvm, charValue);
193 }
194 break;
195 case DC_SIGCHAR_UCHAR:
196 {
197 unsigned char charValue;
198 switch(type_id)
199 {
200 case LGLSXP: charValue = (unsigned char) LOGICAL(arg)[0]; break;
201 case INTSXP: charValue = (unsigned char) INTEGER(arg)[0]; break;
202 case REALSXP: charValue = (unsigned char) REAL(arg)[0]; break;
203 case RAWSXP: charValue = (unsigned char) RAW(arg)[0]; break;
204 default: error("Argument type mismatch at position %d: expected C unsigned char convertable value", argpos); /* dummy */ return R_NilValue;
205 }
206 dcArgChar(pvm, *( (char*) &charValue ));
207 }
208 break;
209 case DC_SIGCHAR_SHORT:
210 {
211 short shortValue;
212 switch(type_id)
213 {
214 case LGLSXP: shortValue = (short) LOGICAL(arg)[0]; break;
215 case INTSXP: shortValue = (short) INTEGER(arg)[0]; break;
216 case REALSXP: shortValue = (short) REAL(arg)[0]; break;
217 case RAWSXP: shortValue = (short) RAW(arg)[0]; break;
218 default: error("Argument type mismatch at position %d: expected C short convertable value", argpos); /* dummy */ return R_NilValue;
219 }
220 dcArgShort(pvm, shortValue);
221 }
222 break;
223 case DC_SIGCHAR_USHORT:
224 {
225 unsigned short shortValue;
226 switch(type_id)
227 {
228 case LGLSXP: shortValue = (unsigned short) LOGICAL(arg)[0]; break;
229 case INTSXP: shortValue = (unsigned short) INTEGER(arg)[0]; break;
230 case REALSXP: shortValue = (unsigned short) REAL(arg)[0]; break;
231 case RAWSXP: shortValue = (unsigned short) RAW(arg)[0]; break;
232 default: error("Argument type mismatch at position %d: expected C unsigned short convertable value", argpos); /* dummy */ return R_NilValue;
233 }
234 dcArgShort(pvm, *( (short*) &shortValue ) );
235 }
236 break;
237 case DC_SIGCHAR_LONG:
238 {
239 long longValue;
240 switch(type_id)
241 {
242 case LGLSXP: longValue = (long) LOGICAL(arg)[0]; break;
243 case INTSXP: longValue = (long) INTEGER(arg)[0]; break;
244 case REALSXP: longValue = (long) REAL(arg)[0]; break;
245 case RAWSXP: longValue = (long) RAW(arg)[0]; break;
246 default: error("Argument type mismatch at position %d: expected C long convertable value", argpos); /* dummy */ return R_NilValue;
247 }
248 dcArgLong(pvm, longValue);
249 }
250 break;
251 case DC_SIGCHAR_ULONG:
252 {
253 unsigned long ulongValue;
254 switch(type_id)
255 {
256 case LGLSXP: ulongValue = (unsigned long) LOGICAL(arg)[0]; break;
257 case INTSXP: ulongValue = (unsigned long) INTEGER(arg)[0]; break;
258 case REALSXP: ulongValue = (unsigned long) REAL(arg)[0]; break;
259 case RAWSXP: ulongValue = (unsigned long) RAW(arg)[0]; break;
260 default: error("Argument type mismatch at position %d: expected C unsigned long convertable value", argpos); /* dummy */ return R_NilValue;
261 }
262 dcArgLong(pvm, (unsigned long) ulongValue);
263 }
264 break;
265 case DC_SIGCHAR_INT:
266 {
267 int intValue;
268 switch(type_id)
269 {
270 case LGLSXP: intValue = (int) LOGICAL(arg)[0]; break;
271 case INTSXP: intValue = INTEGER(arg)[0]; break;
272 case REALSXP: intValue = (int) REAL(arg)[0]; break;
273 case RAWSXP: intValue = (int) RAW(arg)[0]; break;
274 default: error("Argument type mismatch at position %d: expected C int convertable value", argpos); /*dummy*/ return R_NilValue;
275 }
276 dcArgInt(pvm, intValue);
277 }
278 break;
279 case DC_SIGCHAR_UINT:
280 {
281 unsigned int intValue;
282 switch(type_id)
283 {
284 case LGLSXP: intValue = (unsigned int) LOGICAL(arg)[0]; break;
285 case INTSXP: intValue = (unsigned int) INTEGER(arg)[0]; break;
286 case REALSXP: intValue = (unsigned int) REAL(arg)[0]; break;
287 case RAWSXP: intValue = (unsigned int) RAW(arg)[0]; break;
288 default: error("Argument type mismatch at position %d: expected C unsigned int convertable value", argpos); /* dummy */ return R_NilValue;
289 }
290 dcArgInt(pvm, * (int*) &intValue);
291 }
292 break;
293 case DC_SIGCHAR_FLOAT:
294 {
295 float floatValue;
296 switch(type_id)
297 {
298 case LGLSXP: floatValue = (float) LOGICAL(arg)[0]; break;
299 case INTSXP: floatValue = (float) INTEGER(arg)[0]; break;
300 case REALSXP: floatValue = (float) REAL(arg)[0]; break;
301 case RAWSXP: floatValue = (float) RAW(arg)[0]; break;
302 default: error("Argument type mismatch at position %d: expected C float convertable value", argpos); /* dummy */ return R_NilValue;
303 }
304 dcArgFloat( pvm, floatValue );
305 }
306 break;
307 case DC_SIGCHAR_DOUBLE:
308 {
309 DCdouble doubleValue;
310 switch(type_id)
311 {
312 case LGLSXP: doubleValue = (double) LOGICAL(arg)[0]; break;
313 case INTSXP: doubleValue = (double) INTEGER(arg)[0]; break;
314 case REALSXP: doubleValue = REAL(arg)[0]; break;
315 case RAWSXP: doubleValue = (double) RAW(arg)[0]; break;
316 default: error("Argument type mismatch at position %d: expected C double convertable value", argpos); /* dummy */ return R_NilValue;
317 }
318 dcArgDouble( pvm, doubleValue );
319 }
320 break;
321 case DC_SIGCHAR_LONGLONG:
322 {
323 DClonglong longlongValue;
324 switch(type_id)
325 {
326 case LGLSXP: longlongValue = (DClonglong) LOGICAL(arg)[0]; break;
327 case INTSXP: longlongValue = (DClonglong) INTEGER(arg)[0]; break;
328 case REALSXP: longlongValue = (DClonglong) REAL(arg)[0]; break;
329 case RAWSXP: longlongValue = (DClonglong) RAW(arg)[0]; break;
330 default: error("Argument type mismatch at position %d: expected C long long (int64_t) convertable value", argpos); /* dummy */ return R_NilValue;
331 }
332 dcArgLongLong( pvm, longlongValue );
333 }
334 break;
335 case DC_SIGCHAR_ULONGLONG:
336 {
337 DCulonglong ulonglongValue;
338 switch(type_id)
339 {
340 case LGLSXP: ulonglongValue = (DCulonglong) LOGICAL(arg)[0]; break;
341 case INTSXP: ulonglongValue = (DCulonglong) INTEGER(arg)[0]; break;
342 case REALSXP: ulonglongValue = (DCulonglong) REAL(arg)[0]; break;
343 case RAWSXP: ulonglongValue = (DCulonglong) RAW(arg)[0]; break;
344 default: error("Argument type mismatch at position %d: expected C unsigned long long (uint64_t) convertable value", argpos); /* dummy */ return R_NilValue;
345 }
346 dcArgLongLong( pvm, *( (DClonglong*)&ulonglongValue ) );
347 }
348 break;
349 case DC_SIGCHAR_POINTER:
350 {
351 DCpointer ptrValue;
352 switch(type_id)
353 {
354 case NILSXP: ptrValue = (DCpointer) 0; break;
355 case CHARSXP: ptrValue = (DCpointer) CHAR(arg); break;
356 case SYMSXP: ptrValue = (DCpointer) PRINTNAME(arg); break;
357 case STRSXP: ptrValue = (DCpointer) CHAR(STRING_ELT(arg,0)); break;
358 case LGLSXP: ptrValue = (DCpointer) LOGICAL(arg); break;
359 case INTSXP: ptrValue = (DCpointer) INTEGER(arg); break;
360 case REALSXP: ptrValue = (DCpointer) REAL(arg); break;
361 case CPLXSXP: ptrValue = (DCpointer) COMPLEX(arg); break;
362 case RAWSXP: ptrValue = (DCpointer) RAW(arg); break;
363 case EXTPTRSXP: ptrValue = R_ExternalPtrAddr(arg); break;
364 // case ENVSXP: ptrValue = (DCpointer) arg; break;
365 default: error("Argument type mismatch at position %d: expected C pointer convertable value", argpos); /* dummy */ return R_NilValue;
366 }
367 dcArgPointer(pvm, ptrValue);
368 }
369 break;
370 case DC_SIGCHAR_STRING:
371 {
372 DCpointer cstringValue;
373 switch(type_id)
374 {
375 case NILSXP: cstringValue = (DCpointer) 0; break;
376 case CHARSXP: cstringValue = (DCpointer) CHAR(arg); break;
377 case SYMSXP: cstringValue = (DCpointer) PRINTNAME(arg); break;
378 case STRSXP: cstringValue = (DCpointer) CHAR( STRING_ELT(arg,0) ); break;
379 case EXTPTRSXP: cstringValue = R_ExternalPtrAddr(arg); break;
380 default: error("Argument type mismatch at position %d: expected C string pointer convertable value", argpos); /* dummy */ return R_NilValue;
381 }
382 dcArgPointer(pvm, cstringValue);
383 }
384 break;
385 default: error("Signature type mismatch at position %d: Unknown token '%c' at argument %d.", ch, argpos); /* dummy */ return R_NilValue;
386 }
387 } else { /* ptrcnt > 0 */
388 DCpointer ptrValue;
389 if (ch == '<') { /* typed high-level struct/union pointer */
390 char const * e;
391 char const * b;
392 char const * n;
393 int l;
394 b = sig;
395 while( isalnum(*sig) || *sig == '_' ) sig++;
396 if (*sig != '>') {
397 error("Invalid signature '%s' - missing '>' marker for structure at argument %d.", signature, argpos);
398 return R_NilValue; /* Dummy */
399 }
400 sig++;
401 /* check pointer type */
402 if (type_id != NILSXP) {
403 SEXP structName = getAttrib(arg, install("struct"));
404 if (structName == R_NilValue) {
405 error("typed pointer needed here");
406 return R_NilValue; /* Dummy */
407 }
408 e = sig-1;
409 l = e - b;
410 n = CHAR(STRING_ELT(structName,0));
411 if ( (strlen(n) != l) || (strncmp(b,n,l) != 0) ) {
412 error("incompatible pointer types");
413 return R_NilValue; /* Dummy */
414 }
415 }
416 switch(type_id) {
417 case NILSXP: ptrValue = (DCpointer) 0; break;
418 case EXTPTRSXP: ptrValue = R_ExternalPtrAddr(arg); break;
419 case RAWSXP: ptrValue = (DCpointer) RAW(arg); break;
420 default: error("internal error: typed-pointer can be external pointers or raw only.");
421 return R_NilValue; /* Dummy */
422 }
423 dcArgPointer(pvm, ptrValue);
424 ptrcnt = 0;
425 } else { /* typed low-level pointers */
426 switch(ch) {
427 case DC_SIGCHAR_VOID:
428 switch(type_id)
429 {
430 case NILSXP: ptrValue = (DCpointer) 0; break;
431 case STRSXP: ptrValue = (DCpointer) CHAR(STRING_ELT(arg,0)); break;
432 case LGLSXP: ptrValue = (DCpointer) LOGICAL(arg); break;
433 case INTSXP: ptrValue = (DCpointer) INTEGER(arg); break;
434 case REALSXP: ptrValue = (DCpointer) REAL(arg); break;
435 case CPLXSXP: ptrValue = (DCpointer) COMPLEX(arg); break;
436 case RAWSXP: ptrValue = (DCpointer) RAW(arg); break;
437 case EXTPTRSXP: ptrValue = R_ExternalPtrAddr(arg); break;
438 default: error("Argument type mismatch at position %d: expected pointer convertable value", argpos);
439 return R_NilValue; /* dummy */
440 }
441 break;
442 case DC_SIGCHAR_CHAR:
443 case DC_SIGCHAR_UCHAR:
444 switch(type_id)
445 {
446 case NILSXP: ptrValue = (DCpointer) 0; break;
447 case STRSXP:
448 if (ptrcnt == 1) {
449 ptrValue = (DCpointer) CHAR( STRING_ELT(arg,0) );
450 } else {
451 error("Argument type mismatch at position %d: expected 'C string' convertable value", argpos);
452 return R_NilValue; /* dummy */
453 }
454 break;
455 case RAWSXP:
456 if (ptrcnt == 1) {
457 ptrValue = RAW(arg);
458 } else {
459 error("Argument type mismatch at position %d: expected 'C string' convertable value", argpos);
460 return R_NilValue; /* dummy */
461 }
462 break;
463 case EXTPTRSXP: ptrValue = R_ExternalPtrAddr(arg); break;
464 default:
465 error("Argument type mismatch at position %d: expected 'C string' convertable value", argpos);
466 return R_NilValue; /* dummy */
467 }
468 break;
469 case DC_SIGCHAR_USHORT:
470 case DC_SIGCHAR_SHORT:
471 error("Signature '*[sS]' not implemented");
472 return R_NilValue; /* dummy */
473 case DC_SIGCHAR_UINT:
474 case DC_SIGCHAR_INT:
475 switch(type_id)
476 {
477 case NILSXP: ptrValue = (DCpointer) 0; break;
478 case INTSXP: ptrValue = (DCpointer) INTEGER(arg); break;
479 default: error("Argument type mismatch at position %d: expected 'pointer to C integer' convertable value", argpos);
480 return R_NilValue; /* dummy */
481 }
482 break;
483 case DC_SIGCHAR_ULONG:
484 case DC_SIGCHAR_LONG:
485 error("Signature '*[jJ]' not implemented");
486 return R_NilValue; /* dummy */
487 case DC_SIGCHAR_ULONGLONG:
488 case DC_SIGCHAR_LONGLONG:
489 error("Signature '*[lJ]' not implemented");
490 return R_NilValue; /* dummy */
491 case DC_SIGCHAR_FLOAT:
492 switch(type_id)
493 {
494 case NILSXP: ptrValue = (DCpointer) 0; break;
495 case RAWSXP:
496 if ( strcmp( CHAR(STRING_ELT(getAttrib(arg, install("class")),0)),"floatraw") == 0 ) {
497 ptrValue = (DCpointer) RAW(arg);
498 } else {
499 error("Argument type mismatch at position %d: expected 'pointer to C double' convertable value", argpos);
500 return R_NilValue; /* dummy */
501 }
502 break;
503 default: error("Argument type mismatch at position %d: expected 'pointer to C double' convertable value", argpos);
504 return R_NilValue; /* dummy */
505 }
506 break;
507 case DC_SIGCHAR_DOUBLE:
508 switch(type_id)
509 {
510 case NILSXP: ptrValue = (DCpointer) 0; break;
511 case REALSXP: ptrValue = (DCpointer) REAL(arg); break;
512 default: error("Argument type mismatch at position %d: expected 'pointer to C double' convertable value", argpos);
513 return R_NilValue; /* dummy */
514 }
515 break;
516 case DC_SIGCHAR_POINTER:
517 case DC_SIGCHAR_STRING:
518 switch(type_id)
519 {
520 case EXTPTRSXP:
521 ptrValue = R_ExternalPtrAddr( arg ); break;
522 default: error("low-level typed pointer on pointer not implemented");
523 return R_NilValue; /* dummy */
524 }
525 break;
526 default:
527 error("low-level typed pointer on C char pointer not implemented");
528 return R_NilValue; /* dummy */
529 }
530 dcArgPointer(pvm, ptrValue);
531 ptrcnt = 0;
532 }
533 }
534 }
535
536
537 if (args != R_NilValue) {
538 error ("Too many arguments for signature '%s'.", signature);
539 return R_NilValue; /* dummy */
540 }
541 /* process return type, invoke call and return R value */
542
543 switch(*sig++) {
544 case DC_SIGCHAR_BOOL: return ScalarLogical( ( dcCallBool(pvm, addr) == DC_FALSE ) ? FALSE : TRUE );
545
546 case DC_SIGCHAR_CHAR: return ScalarInteger( (int) dcCallChar(pvm, addr) );
547 case DC_SIGCHAR_UCHAR: return ScalarInteger( (int) ( (unsigned char) dcCallChar(pvm, addr ) ) );
548
549 case DC_SIGCHAR_SHORT: return ScalarInteger( (int) dcCallShort(pvm,addr) );
550 case DC_SIGCHAR_USHORT: return ScalarInteger( (int) ( (unsigned short) dcCallShort(pvm,addr) ) );
551
552 case DC_SIGCHAR_INT: return ScalarInteger( dcCallInt(pvm,addr) );
553 case DC_SIGCHAR_UINT: return ScalarReal( (double) (unsigned int) dcCallInt(pvm, addr) );
554
555 case DC_SIGCHAR_LONG: return ScalarReal( (double) dcCallLong(pvm, addr) );
556 case DC_SIGCHAR_ULONG: return ScalarReal( (double) ( (unsigned long) dcCallLong(pvm, addr) ) );
557
558 case DC_SIGCHAR_LONGLONG: return ScalarReal( (double) dcCallLongLong(pvm, addr) );
559 case DC_SIGCHAR_ULONGLONG: return ScalarReal( (double) dcCallLongLong(pvm, addr) );
560
561 case DC_SIGCHAR_FLOAT: return ScalarReal( (double) dcCallFloat(pvm,addr) );
562 case DC_SIGCHAR_DOUBLE: return ScalarReal( dcCallDouble(pvm,addr) );
563 case DC_SIGCHAR_POINTER: return R_MakeExternalPtr( dcCallPointer(pvm,addr), R_NilValue, R_NilValue );
564 case DC_SIGCHAR_STRING: return mkString( dcCallPointer(pvm, addr) );
565 case DC_SIGCHAR_VOID: dcCallVoid(pvm,addr); /* TODO: return invisible */ return R_NilValue;
566 case '*':
567 {
568 SEXP ans;
569 ptrcnt = 1;
570 while (*sig == '*') { ptrcnt++; sig++; }
571 switch(*sig) {
572 case '<': {
573 /* struct/union pointers */
574 PROTECT(ans = R_MakeExternalPtr( dcCallPointer(pvm, addr), R_NilValue, R_NilValue ) );
575 char buf[128];
576 const char* begin = ++sig;
577 const char* end = strchr(sig, '>');
578 size_t n = end - begin;
579 strncpy(buf, begin, n);
580 buf[n] = '\0';
581 setAttrib(ans, install("struct"), mkString(buf) );
582 setAttrib(ans, install("class"), mkString("struct") );
583 } break;
584 case 'C':
585 case 'c': {
586 PROTECT(ans = mkString( dcCallPointer(pvm, addr) ) );
587 } break;
588 case 'v': {
589 PROTECT(ans = R_MakeExternalPtr( dcCallPointer(pvm, addr), R_NilValue, R_NilValue ) );
590 } break;
591 default: error("Unsupported return type signature"); return R_NilValue;
592 }
593 UNPROTECT(1);
594 return(ans);
595 }
596 default: error("Unknown return type specification for signature '%s'.", signature);
597 return R_NilValue; /* dummy */
598 }
599
600 }
601