comparison R/rdc/src/api.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 #include <R.h>
2 #define USE_RINTERNALS
3 #include <Rinternals.h>
4 #include <R_ext/Rdynload.h>
5 #include "dynload.h"
6 #include "dyncall.h"
7 #include "dyncall_signature.h"
8
9
10 /* rdcLoad */
11
12 SEXP rdcLoad(SEXP sLibPath)
13 {
14 void* libHandle;
15 const char* libPath;
16 SEXP r;
17 libPath = CHAR(STRING_ELT(sLibPath,0));
18
19 libHandle = dlLoadLibrary(libPath);
20
21 if (!libHandle) {
22 error("rdcLoad failed on path %s", libPath );
23 }
24
25 r = R_NilValue;
26
27 PROTECT( r = R_MakeExternalPtr(libHandle, R_NilValue, R_NilValue) );
28 UNPROTECT(1);
29
30 return r;
31 }
32
33 /* rdcFree */
34
35 SEXP rdcFree(SEXP sLibHandle)
36 {
37 void* libHandle;
38
39 libHandle = R_ExternalPtrAddr(sLibHandle);
40 dlFreeLibrary( libHandle );
41
42 R_SetExternalPtrAddr(sLibHandle, 0);
43 return R_NilValue;
44 }
45
46 /* rdcFind */
47
48 SEXP rdcFind(SEXP sLibHandle, SEXP sSymbol)
49 {
50 void* libHandle;
51 const char* symbol;
52 void* addr;
53 SEXP r;
54 libHandle = R_ExternalPtrAddr(sLibHandle);
55 symbol = CHAR(STRING_ELT(sSymbol,0) );
56 addr = dlFindSymbol( libHandle, symbol );
57
58 r = R_NilValue;
59
60 PROTECT( r = R_MakeExternalPtr(addr, R_NilValue, R_NilValue) );
61 UNPROTECT(1);
62
63 return r;
64 }
65
66 SEXP r_dcCall(SEXP sCallVM, SEXP sFuncPtr, SEXP sSignature, SEXP sArgs)
67 {
68 DCCallVM* pvm;
69 void* funcPtr;
70 const char* signature;
71 const char* ptr;
72 int i,l,protect_count;
73 SEXP r;
74
75 pvm = R_ExternalPtrAddr(sCallVM);
76 if (!pvm) error("callvm is null");
77
78 funcPtr = R_ExternalPtrAddr(sFuncPtr);
79 if (!funcPtr) error("funcptr is null");
80
81 signature = CHAR(STRING_ELT(sSignature,0) );
82 if (!signature) error("signature is null");
83
84 dcReset(pvm);
85 ptr = signature;
86
87 l = LENGTH(sArgs);
88 i = 0;
89 protect_count = 0;
90 for(;;) {
91 char ch = *ptr++;
92 SEXP arg;
93
94 if (ch == '\0') error("invalid signature - no return type specified");
95
96 if (ch == ')') break;
97
98 if (i >= l) error("not enough arguments for given signature (arg length = %d %d %c)", l,i,ch );
99
100 arg = VECTOR_ELT(sArgs,i);
101 switch(ch) {
102 case DC_SIGCHAR_BOOL:
103 {
104 DCbool value;
105 if ( isLogical(arg) )
106 {
107 value = ( LOGICAL(arg)[0] == 0 ) ? DC_FALSE : DC_TRUE;
108 }
109 else
110 {
111 value = LOGICAL( coerceVector(arg, LGLSXP) )[0] ? DC_FALSE : DC_TRUE;
112 }
113 dcArgBool(pvm, value );
114 break;
115 }
116 case DC_SIGCHAR_INT:
117 {
118 int value;
119 if ( isInteger(arg) )
120 {
121 value = INTEGER(arg)[0];
122 }
123 else
124 {
125 value = INTEGER( coerceVector(arg, INTSXP) )[0];
126 }
127 dcArgInt(pvm, value);
128 break;
129 }
130 case DC_SIGCHAR_FLOAT:
131 {
132 dcArgFloat( pvm, (float) REAL( coerceVector(arg, REALSXP) )[0] );
133 break;
134 }
135 case DC_SIGCHAR_DOUBLE:
136 {
137 double value;
138 if ( isReal(arg) )
139 {
140 value = REAL(arg)[0];
141 }
142 else
143 {
144 value = REAL( coerceVector(arg,REALSXP) )[0];
145 }
146 dcArgDouble( pvm, value );
147 break;
148 }
149 /*
150 case DC_SIGCHAR_LONG:
151 {
152 PROTECT(arg = coerceVector(arg, REALSXP) );
153 dcArgLong( pvm, (DClong) ( REAL(arg)[0] ) );
154 UNPROTECT(1);
155 break;
156 }
157 */
158 case DC_SIGCHAR_STRING:
159 {
160 DCpointer ptr;
161 if (arg == R_NilValue) ptr = (DCpointer) 0;
162 else if (isString(arg)) ptr = (DCpointer) CHAR( STRING_ELT(arg,0) );
163 else {
164 if (protect_count) UNPROTECT(protect_count);
165 error("invalid value for C string argument"); break;
166 }
167 }
168 case DC_SIGCHAR_POINTER:
169 {
170 DCpointer ptr;
171 if ( arg == R_NilValue ) ptr = (DCpointer) 0;
172 else if (isString(arg) ) ptr = (DCpointer) CHAR( STRING_ELT(arg,0) );
173 else if (isReal(arg) ) ptr = (DCpointer) REAL(arg);
174 else if (isInteger(arg) ) ptr = (DCpointer) INTEGER(arg);
175 else if (isLogical(arg) ) ptr = (DCpointer) LOGICAL(arg);
176 else if (TYPEOF(arg) == EXTPTRSXP) ptr = R_ExternalPtrAddr(arg);
177 else {
178 if (protect_count) UNPROTECT(protect_count);
179 error("invalid signature"); break;
180 }
181 dcArgPointer(pvm, ptr);
182 break;
183 }
184 }
185 ++i;
186 }
187
188 if ( i != l )
189 {
190 if (protect_count)
191 UNPROTECT(protect_count);
192 error ("signature claims to have %d arguments while %d arguments are given", i, l);
193 }
194
195 switch(*ptr) {
196 case DC_SIGCHAR_BOOL:
197 PROTECT( r = allocVector(LGLSXP, 1) ); protect_count++;
198 LOGICAL(r)[0] = ( dcCallBool(pvm, funcPtr) == DC_FALSE ) ? FALSE : TRUE;
199 UNPROTECT(protect_count);
200 return r;
201 case DC_SIGCHAR_CHAR:
202 PROTECT( r = allocVector(INTSXP, 1) ); protect_count++;
203 INTEGER(r)[0] = dcCallChar(pvm, funcPtr);
204 UNPROTECT(protect_count);
205 return r;
206 case DC_SIGCHAR_SHORT:
207 PROTECT( r = allocVector(INTSXP, 1) ); protect_count++;
208 INTEGER(r)[0] = dcCallShort(pvm, funcPtr);
209 UNPROTECT(protect_count);
210 return r;
211 case DC_SIGCHAR_LONG:
212 PROTECT( r = allocVector(INTSXP, 1) ); protect_count++;
213 INTEGER(r)[0] = dcCallLong(pvm, funcPtr);
214 UNPROTECT(protect_count);
215 return r;
216 case DC_SIGCHAR_INT:
217 PROTECT( r = allocVector(INTSXP, 1) ); protect_count++;
218 INTEGER(r)[0] = dcCallInt(pvm, funcPtr);
219 UNPROTECT(protect_count);
220 return r;
221 case DC_SIGCHAR_LONGLONG:
222 PROTECT( r = allocVector(REALSXP, 1) ); protect_count++;
223 REAL(r)[0] = (double) ( dcCallLong(pvm, funcPtr) );
224 UNPROTECT(protect_count);
225 return r;
226 case DC_SIGCHAR_FLOAT:
227 PROTECT( r = allocVector(REALSXP, 1) ); protect_count++;
228 REAL(r)[0] = (double) ( dcCallFloat(pvm, funcPtr) );
229 UNPROTECT(protect_count);
230 return r;
231 case DC_SIGCHAR_DOUBLE:
232 PROTECT( r = allocVector(REALSXP, 1) );
233 protect_count++;
234 REAL(r)[0] = dcCallDouble(pvm, funcPtr);
235 UNPROTECT(protect_count);
236 return r;
237 case DC_SIGCHAR_POINTER:
238 PROTECT( r = R_MakeExternalPtr( dcCallPointer(pvm,funcPtr), R_NilValue, R_NilValue ) );
239 protect_count++;
240 UNPROTECT(protect_count);
241 return r;
242 case DC_SIGCHAR_VOID:
243 dcCallVoid(pvm,funcPtr);
244 if (protect_count) UNPROTECT(protect_count);
245 break;
246 default:
247 {
248 if (protect_count)
249 UNPROTECT(protect_count);
250 error("invalid return type signature");
251 }
252 break;
253 }
254 return R_NilValue;
255
256 }
257
258 /* rdcCall */
259
260 DCCallVM* gCall;
261
262 SEXP rdcCall(SEXP sFuncPtr, SEXP sSignature, SEXP sArgs)
263 {
264 void* funcPtr;
265 const char* signature;
266 const char* ptr;
267 int i,l,protect_count;
268 SEXP r;
269
270 funcPtr = R_ExternalPtrAddr(sFuncPtr);
271
272 if (!funcPtr) error("funcptr is null");
273
274 signature = CHAR(STRING_ELT(sSignature,0) );
275
276 if (!signature) error("signature is null");
277
278 dcReset(gCall);
279 ptr = signature;
280
281 l = LENGTH(sArgs);
282 i = 0;
283 protect_count = 0;
284 for(;;) {
285 char ch = *ptr++;
286 SEXP arg;
287
288 if (ch == '\0') error("invalid signature - no return type specified");
289
290 if (ch == ')') break;
291
292 if (i >= l) error("not enough arguments for given signature (arg length = %d %d %c)", l,i,ch );
293
294 arg = VECTOR_ELT(sArgs,i);
295 switch(ch) {
296 case DC_SIGCHAR_BOOL:
297 {
298 if ( !isLogical(arg) )
299 {
300 PROTECT(arg = coerceVector(arg, LGLSXP));
301 protect_count++;
302 }
303 dcArgBool(gCall, ( LOGICAL(arg)[0] == 0 ) ? DC_FALSE : DC_TRUE );
304 // UNPROTECT(1);
305 break;
306 }
307 case DC_SIGCHAR_INT:
308 {
309 if ( !isInteger(arg) )
310 {
311 PROTECT(arg = coerceVector(arg, INTSXP));
312 protect_count++;
313 }
314 dcArgInt(gCall, INTEGER(arg)[0]);
315 // UNPROTECT(1);
316 break;
317 }
318 case DC_SIGCHAR_FLOAT:
319 {
320 PROTECT(arg = coerceVector(arg, REALSXP) );
321 dcArgFloat( gCall, REAL(arg)[0] );
322 UNPROTECT(1);
323 break;
324 }
325 case DC_SIGCHAR_DOUBLE:
326 {
327 if ( !isReal(arg) )
328 {
329 PROTECT(arg = coerceVector(arg, REALSXP) );
330 protect_count++;
331 }
332 dcArgDouble( gCall, REAL(arg)[0] );
333 // UNPROTECT(1);
334 break;
335 }
336 /*
337 case DC_SIGCHAR_LONG:
338 {
339 PROTECT(arg = coerceVector(arg, REALSXP) );
340 dcArgLong( gCall, (DClong) ( REAL(arg)[0] ) );
341 UNPROTECT(1);
342 break;
343 }
344 */
345 case DC_SIGCHAR_STRING:
346 {
347 DCpointer ptr;
348 if (arg == R_NilValue) ptr = (DCpointer) 0;
349 else if (isString(arg)) ptr = (DCpointer) CHAR( STRING_ELT(arg,0) );
350 else {
351 if (protect_count) UNPROTECT(protect_count);
352 error("invalid value for C string argument"); break;
353 }
354 }
355 case DC_SIGCHAR_POINTER:
356 {
357 DCpointer ptr;
358 if ( arg == R_NilValue ) ptr = (DCpointer) 0;
359 else if (isString(arg) ) ptr = (DCpointer) CHAR( STRING_ELT(arg,0) );
360 else if (isReal(arg) ) ptr = (DCpointer) REAL(arg);
361 else if (isInteger(arg) ) ptr = (DCpointer) INTEGER(arg);
362 else if (isLogical(arg) ) ptr = (DCpointer) LOGICAL(arg);
363 else if (TYPEOF(arg) == EXTPTRSXP) ptr = R_ExternalPtrAddr(arg);
364 else {
365 if (protect_count) UNPROTECT(protect_count);
366 error("invalid signature"); break;
367 }
368 dcArgPointer(gCall, ptr);
369 break;
370 }
371 }
372 ++i;
373 }
374
375 if ( i != l )
376 {
377 if (protect_count)
378 UNPROTECT(protect_count);
379 error ("signature claims to have %d arguments while %d arguments are given", i, l);
380 }
381
382 switch(*ptr) {
383 case DC_SIGCHAR_BOOL:
384 PROTECT( r = allocVector(LGLSXP, 1) ); protect_count++;
385 LOGICAL(r)[0] = ( dcCallBool(gCall, funcPtr) == DC_FALSE ) ? FALSE : TRUE;
386 UNPROTECT(protect_count);
387 return r;
388 case DC_SIGCHAR_INT:
389 PROTECT( r = allocVector(INTSXP, 1) ); protect_count++;
390 INTEGER(r)[0] = dcCallInt(gCall, funcPtr);
391 UNPROTECT(protect_count);
392 return r;
393 case DC_SIGCHAR_LONG:
394 PROTECT( r = allocVector(REALSXP, 1) ); protect_count++;
395 REAL(r)[0] = (double) ( dcCallLong(gCall, funcPtr) );
396 UNPROTECT(protect_count);
397 return r;
398 case DC_SIGCHAR_FLOAT:
399 PROTECT( r = allocVector(REALSXP, 1) ); protect_count++;
400 REAL(r)[0] = (double) ( dcCallFloat(gCall, funcPtr) );
401 UNPROTECT(protect_count);
402 return r;
403 case DC_SIGCHAR_DOUBLE:
404 PROTECT( r = allocVector(REALSXP, 1) );
405 protect_count++;
406 REAL(r)[0] = dcCallDouble(gCall, funcPtr);
407 UNPROTECT(protect_count);
408 return r;
409 case DC_SIGCHAR_POINTER:
410 PROTECT( r = R_MakeExternalPtr( dcCallPointer(gCall,funcPtr), R_NilValue, R_NilValue ) );
411 protect_count++;
412 UNPROTECT(protect_count);
413 return r;
414 case DC_SIGCHAR_VOID:
415 dcCallVoid(gCall,funcPtr);
416 if (protect_count) UNPROTECT(protect_count);
417 break;
418 default:
419 {
420 if (protect_count)
421 UNPROTECT(protect_count);
422 error("invalid return type signature");
423 }
424 }
425 return R_NilValue;
426 }
427
428 SEXP rdcUnpack1(SEXP ptr_x, SEXP offset, SEXP sig_x)
429 {
430 char* ptr = ( (char*) R_ExternalPtrAddr(ptr_x) ) + INTEGER(offset)[0];
431 const char* sig = CHAR(STRING_ELT(sig_x,0) );
432 switch(sig[0])
433 {
434 case DC_SIGCHAR_CHAR: return ScalarInteger( ( (unsigned char*)ptr)[0] );
435 case DC_SIGCHAR_INT: return ScalarInteger( ( (int*)ptr )[0] );
436 case DC_SIGCHAR_FLOAT: return ScalarReal( (double) ( (float*) ptr )[0] );
437 case DC_SIGCHAR_DOUBLE: return ScalarReal( ((double*)ptr)[0] );
438 default: error("invalid signature");
439 }
440 return R_NilValue;
441 }
442
443 SEXP rdcDataPtr(SEXP x, SEXP offset)
444 {
445 void* ptr = ( ( (unsigned char*) DATAPTR(x) ) + INTEGER(offset)[0] );
446 return R_MakeExternalPtr( ptr, R_NilValue, R_NilValue );
447 }
448
449 SEXP rdcMode(SEXP id)
450 {
451 dcMode( gCall, INTEGER(id)[0] );
452 dcReset( gCall );
453 return R_NilValue;
454 }
455
456 SEXP r_dcNewCallVM(SEXP size)
457 {
458 return R_MakeExternalPtr( dcNewCallVM( INTEGER(size)[0] ), R_NilValue, R_NilValue );
459 }
460
461 SEXP r_dcFree(SEXP callvm)
462 {
463 DCCallVM* pvm = R_ExternalPtrAddr(callvm);
464 dcFree(pvm);
465 return R_NilValue;
466 }
467
468 SEXP r_dcMode(SEXP callvm, SEXP id)
469 {
470 DCCallVM* pvm = R_ExternalPtrAddr(callvm);
471 dcMode( pvm, INTEGER(id)[0] );
472 dcReset( pvm );
473 return R_NilValue;
474 }
475
476 /* register R to C calls */
477
478 R_CallMethodDef callMethods[] =
479 {
480 {"rdcLoad", (DL_FUNC) &rdcLoad, 1},
481 {"rdcFree", (DL_FUNC) &rdcFree, 1},
482 {"rdcFind", (DL_FUNC) &rdcFind, 2},
483 {"rdcCall", (DL_FUNC) &rdcCall, 3},
484 {"rdcUnpack1", (DL_FUNC) &rdcUnpack1, 3},
485 {"rdcDataPtr", (DL_FUNC) &rdcDataPtr, 2},
486 {"rdcMode", (DL_FUNC) &rdcMode, 1},
487
488 {"dcNewCallVM", (DL_FUNC) &r_dcNewCallVM, 1},
489 {"dcFree", (DL_FUNC) &r_dcFree, 1},
490 {"dcCall", (DL_FUNC) &r_dcCall, 4},
491 {"dcMode", (DL_FUNC) &r_dcMode, 2},
492
493 {NULL, NULL, 0}
494 };
495
496 void R_init_rdc(DllInfo *info)
497 {
498 R_registerRoutines(info, NULL, callMethods, NULL, NULL);
499 gCall = dcNewCallVM(4096);
500 }
501
502 void R_unload_rdc(DllInfo *info)
503 {
504 }
505