annotate R/rdyncall/src/rpack.c @ 63:9b6cdffd30dd

- further fixes of inccorect overflow errors for int (and long on LLP64 systems) * prev commit had bugs * added overflow tests for also int, long, long long (for both, lp64 and llp64) - while at it, fixing a reference leak when not using python with utf8 caching
author Tassilo Philipp
date Sun, 19 May 2024 15:33:18 +0200
parents 0cfcc391201f
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
1 /** ===========================================================================
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
2 ** R-Package: rdyncall
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
3 ** File: src/rpack.c
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
4 ** Description: (un-)packing of C structure data
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
5 ** TODO
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
6 ** - support for bitfields
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
7 **/
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
8
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
9 // #define USE_RINTERNALS
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
10 #include <Rinternals.h>
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
11 #include <string.h>
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
12 #include <stddef.h>
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
13 #include "rdyncall_signature.h"
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
14 /** ---------------------------------------------------------------------------
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
15 ** C-Function: r_dataptr
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
16 ** Description: retrieve the 'data' pointer on an R expression.
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
17 ** R-Calling Convention: .Call
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
18 **
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
19 **/
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
20
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
21 static char* r_dataptr(SEXP x, SEXP off, size_t element_size)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
22 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
23 if ( LENGTH(off) == 0 ) error("missing offset");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
24 char* p = NULL;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
25 ptrdiff_t o = INTEGER(off)[0], s = 0;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
26
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
27 switch(TYPEOF(x))
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
28 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
29 case CHARSXP: p = (char*) CHAR(x); s = LENGTH(x)*sizeof(char); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
30 case LGLSXP: p = (char*) LOGICAL(x); s = LENGTH(x)*sizeof(Rboolean); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
31 case INTSXP: p = (char*) INTEGER(x); s = LENGTH(x)*sizeof(int); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
32 case REALSXP: p = (char*) REAL(x); s = LENGTH(x)*sizeof(double); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
33 case CPLXSXP: p = (char*) COMPLEX(x); s = LENGTH(x)*sizeof(Rcomplex); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
34 case STRSXP: p = (char*) CHAR( STRING_ELT(x,0) ); s = strlen(p)*sizeof(char); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
35 case RAWSXP: p = (char*) RAW(x); s = LENGTH(x)*sizeof(char); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
36 case EXTPTRSXP: return (char*) R_ExternalPtrAddr(x) + o; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
37 default: error("invalid object type"); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
38 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
39 if (p == NULL) error("NULL address pointer");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
40 if (o < 0 || o+element_size > s) error("offset %d is out-of-bounds of the R object (max size %d)", o, s);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
41 return p + o;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
42 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
43
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
44
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
45
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
46 /** ---------------------------------------------------------------------------
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
47 ** C-Function: r_pack
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
48 ** Description: pack R data type into a C data type
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
49 ** R-Calling Convention: .Call
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
50 **
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
51 **/
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
52 SEXP r_pack(SEXP ptr_x, SEXP offset, SEXP sig_x, SEXP value_x)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
53 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
54 int type_of = TYPEOF(value_x);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
55 const char* sig = CHAR(STRING_ELT(sig_x,0) );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
56 switch(sig[0])
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
57 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
58 case DC_SIGCHAR_BOOL:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
59 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
60 int* Bp = (int*) r_dataptr(ptr_x, offset, sizeof(Rboolean));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
61 switch(type_of)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
62 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
63 case LGLSXP: *Bp = (int) LOGICAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
64 case INTSXP: *Bp = (int) ( INTEGER(value_x)[0] == 0) ? 0 : 1; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
65 case REALSXP: *Bp = (int) ( REAL(value_x)[0] == 0.0) ? 0 : 1; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
66 case RAWSXP: *Bp = (int) ( RAW(value_x)[0] == 0) ? 0 : 1; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
67 default: error("value mismatch with 'B' pack type");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
68 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
69 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
70 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
71 case DC_SIGCHAR_CHAR:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
72 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
73 char* cp = (char*) r_dataptr(ptr_x, offset, sizeof(char));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
74 switch(type_of)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
75 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
76 case LGLSXP: *cp = (char) LOGICAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
77 case INTSXP: *cp = (char) INTEGER(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
78 case REALSXP: *cp = (char) REAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
79 case RAWSXP: *cp = (char) RAW(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
80 default: error("value mismatch with 'c' pack type");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
81 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
82 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
83 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
84 case DC_SIGCHAR_UCHAR:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
85 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
86 unsigned char* cp = (unsigned char*) r_dataptr(ptr_x,offset,sizeof(unsigned char));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
87 switch(type_of)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
88 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
89 case LGLSXP: *cp = (unsigned char) LOGICAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
90 case INTSXP: *cp = (unsigned char) INTEGER(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
91 case REALSXP: *cp = (unsigned char) REAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
92 case RAWSXP: *cp = (unsigned char) RAW(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
93 default: error("value mismatch with 'C' pack type");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
94 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
95 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
96 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
97 case DC_SIGCHAR_SHORT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
98 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
99 short* sp = (short*) r_dataptr(ptr_x,offset,sizeof(short));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
100 switch(type_of)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
101 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
102 case LGLSXP: *sp = (short) LOGICAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
103 case INTSXP: *sp = (short) INTEGER(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
104 case REALSXP: *sp = (short) REAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
105 case RAWSXP: *sp = (short) RAW(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
106 default: error("value mismatch with 's' pack type");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
107 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
108 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
109 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
110 case DC_SIGCHAR_USHORT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
111 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
112 unsigned short* sp = (unsigned short*) r_dataptr(ptr_x,offset,sizeof(unsigned short));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
113 switch(type_of)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
114 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
115 case LGLSXP: *sp = (unsigned short) LOGICAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
116 case INTSXP: *sp = (unsigned short) INTEGER(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
117 case REALSXP: *sp = (unsigned short) REAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
118 case RAWSXP: *sp = (unsigned short) RAW(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
119 default: error("value mismatch with 'S' pack type");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
120 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
121 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
122 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
123 case DC_SIGCHAR_INT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
124 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
125 int* ip = (int*) r_dataptr(ptr_x,offset,sizeof(int));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
126 switch(type_of)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
127 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
128 case LGLSXP: *ip = (int) LOGICAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
129 case INTSXP: *ip = (int) INTEGER(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
130 case REALSXP: *ip = (int) REAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
131 case RAWSXP: *ip = (int) RAW(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
132 default: error("value mismatch with 'i' pack type");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
133 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
134 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
135 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
136 case DC_SIGCHAR_UINT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
137 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
138 unsigned int* ip = (unsigned int*) r_dataptr(ptr_x,offset,sizeof(unsigned int));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
139 switch(type_of)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
140 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
141 case LGLSXP: *ip = (unsigned int) LOGICAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
142 case INTSXP: *ip = (unsigned int) INTEGER(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
143 case REALSXP: *ip = (unsigned int) REAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
144 case RAWSXP: *ip = (unsigned int) RAW(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
145 default: error("value mismatch with 'I' pack type");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
146 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
147 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
148 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
149 case DC_SIGCHAR_LONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
150 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
151 long* ip = (long*) r_dataptr(ptr_x,offset,sizeof(long));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
152 switch(type_of)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
153 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
154 case LGLSXP: *ip = (long) LOGICAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
155 case INTSXP: *ip = (long) INTEGER(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
156 case REALSXP: *ip = (long) REAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
157 case RAWSXP: *ip = (long) RAW(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
158 default: error("value mismatch with 'j' pack type");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
159 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
160 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
161 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
162 case DC_SIGCHAR_ULONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
163 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
164 unsigned long* ip = (unsigned long*) r_dataptr(ptr_x,offset,sizeof(unsigned long));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
165 switch(type_of)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
166 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
167 case LGLSXP: *ip = (unsigned long) LOGICAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
168 case INTSXP: *ip = (unsigned long) INTEGER(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
169 case REALSXP: *ip = (unsigned long) REAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
170 case RAWSXP: *ip = (unsigned long) RAW(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
171 default: error("value mismatch with 'J' pack type");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
172 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
173 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
174 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
175 case DC_SIGCHAR_LONGLONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
176 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
177 long long* Lp = (long long*) r_dataptr(ptr_x,offset,sizeof(long long));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
178 switch(type_of)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
179 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
180 case LGLSXP: *Lp = (long long) LOGICAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
181 case INTSXP: *Lp = (long long) INTEGER(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
182 case REALSXP: *Lp = (long long) REAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
183 case RAWSXP: *Lp = (long long) RAW(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
184 default: error("value mismatch with 'l' pack type");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
185 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
186 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
187 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
188 case DC_SIGCHAR_ULONGLONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
189 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
190 unsigned long long* Lp = (unsigned long long*) r_dataptr(ptr_x,offset,sizeof(unsigned long long));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
191 switch(type_of)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
192 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
193 case LGLSXP: *Lp = (unsigned long long) LOGICAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
194 case INTSXP: *Lp = (unsigned long long) INTEGER(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
195 case REALSXP: *Lp = (unsigned long long) REAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
196 case RAWSXP: *Lp = (unsigned long long) RAW(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
197 default: error("value mismatch with 'L' pack type");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
198 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
199 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
200 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
201 case DC_SIGCHAR_FLOAT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
202 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
203 float* fp = (float*) r_dataptr(ptr_x,offset,sizeof(float));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
204 switch(type_of)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
205 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
206 case LGLSXP: *fp = (float) LOGICAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
207 case INTSXP: *fp = (float) INTEGER(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
208 case REALSXP: *fp = (float) REAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
209 case RAWSXP: *fp = (float) RAW(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
210 default: error("value mismatch with 'f' pack type");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
211 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
212 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
213 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
214 case DC_SIGCHAR_DOUBLE:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
215 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
216 double* dp = (double*) r_dataptr(ptr_x,offset,sizeof(double));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
217 switch(type_of)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
218 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
219 case LGLSXP: *dp = (double) LOGICAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
220 case INTSXP: *dp = (double) INTEGER(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
221 case REALSXP: *dp = (double) REAL(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
222 case RAWSXP: *dp = (double) RAW(value_x)[0]; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
223 default: error("value mismatch with 'd' pack type");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
224 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
225 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
226 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
227 case DC_SIGCHAR_POINTER:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
228 case '*':
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
229 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
230 void** pp = (void**) r_dataptr(ptr_x,offset,sizeof(void*));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
231 switch(type_of)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
232 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
233 case NILSXP: *pp = (void*) 0; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
234 case CHARSXP: *pp = (void*) CHAR(value_x); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
235 case LGLSXP: *pp = (void*) LOGICAL(value_x); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
236 case INTSXP: *pp = (void*) INTEGER(value_x); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
237 case REALSXP: *pp = (void*) REAL(value_x); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
238 case CPLXSXP: *pp = (void*) COMPLEX(value_x); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
239 case STRSXP: *pp = (void*) CHAR( STRING_ELT(value_x,0) ); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
240 case EXTPTRSXP:*pp = (void*) R_ExternalPtrAddr(value_x); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
241 case RAWSXP: *pp = (void*) RAW(value_x); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
242 default: error("value type mismatch with 'p' pack type");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
243 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
244 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
245 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
246 case DC_SIGCHAR_STRING:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
247 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
248 char** Sp = (char**) r_dataptr(ptr_x,offset,sizeof(char*));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
249 switch(type_of)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
250 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
251 case NILSXP: *Sp = (char*) NULL; break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
252 case CHARSXP: *Sp = (char*) CHAR(value_x); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
253 case STRSXP: *Sp = (char*) CHAR( STRING_ELT(value_x,0) ); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
254 case EXTPTRSXP:*Sp = (char*) R_ExternalPtrAddr(value_x); break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
255 default: error("value type mismatch with 'Z' pack type");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
256 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
257 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
258 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
259 case DC_SIGCHAR_SEXP:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
260 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
261 SEXP* px = (SEXP*) r_dataptr(ptr_x,offset,sizeof(SEXP*));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
262 *px = value_x;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
263 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
264 break;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
265 default: error("invalid signature");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
266 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
267 return R_NilValue;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
268 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
269
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
270 /** ---------------------------------------------------------------------------
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
271 ** C-Function: r_unpack
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
272 ** Description: unpack elements from C-like structures to R values.
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
273 ** R-Calling Convention: .Call
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
274 **
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
275 **/
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
276 SEXP r_unpack(SEXP ptr_x, SEXP offset, SEXP sig_x)
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
277 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
278 char* ptr = NULL;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
279 const char* sig = CHAR(STRING_ELT(sig_x,0) );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
280 switch(sig[0])
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
281 {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
282 case DC_SIGCHAR_BOOL:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
283 ptr = r_dataptr(ptr_x,offset,sizeof(Rboolean));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
284 return ScalarLogical( ((int*)ptr)[0] );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
285 case DC_SIGCHAR_CHAR:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
286 ptr = r_dataptr(ptr_x,offset,sizeof(char));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
287 return ScalarInteger( ( (char*)ptr)[0] );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
288 case DC_SIGCHAR_UCHAR:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
289 ptr = r_dataptr(ptr_x,offset,sizeof(unsigned char));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
290 return ScalarInteger( ( (unsigned char*)ptr)[0] );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
291 case DC_SIGCHAR_SHORT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
292 ptr = r_dataptr(ptr_x,offset,sizeof(short));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
293 return ScalarInteger( ( (short*)ptr)[0] );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
294 case DC_SIGCHAR_USHORT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
295 ptr = r_dataptr(ptr_x,offset,sizeof(unsigned short));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
296 return ScalarInteger( ( (unsigned short*)ptr)[0] );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
297 case DC_SIGCHAR_INT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
298 ptr = r_dataptr(ptr_x,offset,sizeof(int));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
299 return ScalarInteger( ( (int*)ptr )[0] );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
300 case DC_SIGCHAR_UINT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
301 ptr = r_dataptr(ptr_x,offset,sizeof(unsigned int));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
302 return ScalarReal( (double) ( (unsigned int*)ptr )[0] );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
303 case DC_SIGCHAR_LONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
304 ptr = r_dataptr(ptr_x,offset,sizeof(long));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
305 return ScalarReal( (double) ( (long*)ptr )[0] );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
306 case DC_SIGCHAR_ULONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
307 ptr = r_dataptr(ptr_x,offset,sizeof(unsigned long));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
308 return ScalarReal( (double) ( (unsigned long*) ptr )[0] );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
309 case DC_SIGCHAR_FLOAT:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
310 ptr = r_dataptr(ptr_x,offset,sizeof(float));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
311 return ScalarReal( (double) ( (float*) ptr )[0] );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
312 case DC_SIGCHAR_DOUBLE:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
313 ptr = r_dataptr(ptr_x,offset,sizeof(double));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
314 return ScalarReal( ((double*)ptr)[0] );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
315 case DC_SIGCHAR_LONGLONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
316 ptr = r_dataptr(ptr_x,offset,sizeof(long long));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
317 return ScalarReal( (double) ( ((long long*)ptr)[0] ) );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
318 case DC_SIGCHAR_ULONGLONG:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
319 ptr = r_dataptr(ptr_x,offset,sizeof(unsigned long long));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
320 return ScalarReal( (double) ( ((unsigned long long*)ptr)[0] ) );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
321 case '*':
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
322 case DC_SIGCHAR_POINTER:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
323 ptr = r_dataptr(ptr_x,offset,sizeof(void*));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
324 return R_MakeExternalPtr( ((void**)ptr)[0] , R_NilValue, R_NilValue );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
325 case DC_SIGCHAR_STRING: {
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
326 ptr = r_dataptr(ptr_x,offset,sizeof(char*));
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
327 char* s = ( (char**) ptr )[0];
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
328 if (s == NULL) return R_MakeExternalPtr( 0, R_NilValue, R_NilValue );
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
329 return mkString(s);
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
330 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
331 case DC_SIGCHAR_SEXP:
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
332 return (SEXP) ptr;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
333 default: error("invalid signature");
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
334 }
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
335 return R_NilValue;
0cfcc391201f initial from svn dyncall-1745
Daniel Adler
parents:
diff changeset
336 }