10609
|
1 |
"
|
|
2 |
COPYRIGHT (c) 2007 by eXept Software AG
|
|
3 |
All Rights Reserved
|
|
4 |
|
|
5 |
This software is furnished under a license and may be used
|
|
6 |
only in accordance with the terms of that license and with the
|
|
7 |
inclusion of the above copyright notice. This software may not
|
|
8 |
be provided or otherwise made available to, or used by, any
|
|
9 |
other person. No title to or ownership of the software is
|
|
10 |
hereby transferred.
|
|
11 |
"
|
|
12 |
"{ Package: 'stx:libbasic' }"
|
10607
|
13 |
|
|
14 |
ExternalBytes subclass:#ExternalFunctionCallback
|
|
15 |
instanceVariableNames:'returnType argumentTypes action'
|
10609
|
16 |
classVariableNames:'CallBackRegistry Verbose'
|
10607
|
17 |
poolDictionaries:''
|
|
18 |
category:'System-Support'
|
|
19 |
!
|
|
20 |
|
|
21 |
!ExternalFunctionCallback primitiveDefinitions!
|
|
22 |
%{
|
|
23 |
|
|
24 |
#ifdef HAVE_FFI
|
|
25 |
# include <ffi.h>
|
|
26 |
# define MAX_ARGS 128
|
|
27 |
|
|
28 |
extern ffi_type *__get_ffi_type_sint();
|
|
29 |
extern ffi_type *__get_ffi_type_sint8();
|
|
30 |
extern ffi_type *__get_ffi_type_sint16();
|
|
31 |
extern ffi_type *__get_ffi_type_sint32();
|
|
32 |
extern ffi_type *__get_ffi_type_sint64();
|
|
33 |
extern ffi_type *__get_ffi_type_uint();
|
|
34 |
extern ffi_type *__get_ffi_type_uint8();
|
|
35 |
extern ffi_type *__get_ffi_type_uint16();
|
|
36 |
extern ffi_type *__get_ffi_type_uint32();
|
|
37 |
extern ffi_type *__get_ffi_type_uint64();
|
|
38 |
extern ffi_type *__get_ffi_type_float();
|
|
39 |
extern ffi_type *__get_ffi_type_double();
|
|
40 |
extern ffi_type *__get_ffi_type_void();
|
|
41 |
extern ffi_type *__get_ffi_type_pointer();
|
|
42 |
|
|
43 |
#endif
|
|
44 |
|
|
45 |
%}
|
|
46 |
! !
|
|
47 |
|
|
48 |
!ExternalFunctionCallback primitiveFunctions!
|
|
49 |
%{
|
|
50 |
|
10609
|
51 |
#define xxVERBOSE
|
10607
|
52 |
|
|
53 |
void
|
10609
|
54 |
ExternalFunctionCallback__closure_wrapper_fn(ffi_cif* cif, void* resp, void** args, void* userdata)
|
10607
|
55 |
{
|
10609
|
56 |
int actionIndex = (int)userdata;
|
|
57 |
int i;
|
|
58 |
OBJ st_argVector = nil;
|
|
59 |
OBJ st_actionVector, st_callBack = nil, st_result;
|
|
60 |
OBJFUNC code;
|
|
61 |
ffi_type *retType;
|
|
62 |
INT sintResult;
|
|
63 |
unsigned INT uintResult;
|
|
64 |
float floatResult;
|
|
65 |
double doubleResult;
|
|
66 |
|
|
67 |
if (@global(ExternalFunctionCallback:Verbose) == true) {
|
|
68 |
fprintf(stderr, "ExternalFunctionCallback(wrapper): actionIndex=%d resp*=%x\n", actionIndex, resp);
|
|
69 |
fflush(stderr);
|
|
70 |
fprintf(stderr, "ExternalFunctionCallback(wrapper): nargs=%d\n", cif->nargs);
|
|
71 |
fflush(stderr);
|
|
72 |
}
|
|
73 |
|
|
74 |
st_argVector = __ARRAY_NEW_INT(cif->nargs);
|
|
75 |
|
|
76 |
for (i=0; i<cif->nargs; i++) {
|
|
77 |
ffi_type *argType;
|
|
78 |
OBJ st_arg = nil;
|
|
79 |
|
|
80 |
__PROTECT__(st_argVector);
|
|
81 |
|
|
82 |
argType = cif->arg_types[i];
|
|
83 |
if (argType == __get_ffi_type_sint()) {
|
|
84 |
st_arg = __MKINT( *(int *)(args[i]) );
|
|
85 |
} else if (argType == __get_ffi_type_uint()) {
|
|
86 |
st_arg = __MKUINT( *(unsigned int *)(args[i]) );
|
|
87 |
} else if (argType == __get_ffi_type_uint8()) {
|
|
88 |
st_arg = __MKSMALLINT( *(unsigned char *)(args[i]) );
|
|
89 |
} else if (argType == __get_ffi_type_sint8()) {
|
|
90 |
st_arg = __MKSMALLINT( *(char *)(args[i]) );
|
|
91 |
} else if (argType == __get_ffi_type_uint16()) {
|
|
92 |
st_arg = __MKSMALLINT( *(unsigned short *)(args[i]) );
|
|
93 |
} else if (argType == __get_ffi_type_sint16()) {
|
|
94 |
st_arg = __MKSMALLINT( *(short *)(args[i]) );
|
|
95 |
} else if (argType == __get_ffi_type_uint32()) {
|
|
96 |
st_arg = __MKUINT( *(unsigned int *)(args[i]) );
|
|
97 |
} else if (argType == __get_ffi_type_sint32()) {
|
|
98 |
st_arg = __MKINT( *(int *)(args[i]) );
|
|
99 |
} else if (argType == __get_ffi_type_float()) {
|
|
100 |
st_arg = __MKSFLOAT( *(float *)(args[i]) );
|
|
101 |
} else if (argType == __get_ffi_type_double()) {
|
|
102 |
st_arg = __MKFLOAT( *(double *)(args[i]) );
|
|
103 |
} else if (argType == __get_ffi_type_pointer()) {
|
|
104 |
st_arg = __MKEXTERNALADDRESS( *(void **)(args[i]) );
|
|
105 |
} else {
|
|
106 |
if (@global(ExternalFunctionCallback:Verbose) == true) {
|
|
107 |
fprintf(stderr, "ExternalFunctionCallback(wrapper): invalid argument type %d - arg %d\n", argType, i);
|
|
108 |
}
|
|
109 |
}
|
|
110 |
|
|
111 |
__UNPROTECT__(st_argVector);
|
|
112 |
|
|
113 |
if (@global(ExternalFunctionCallback:Verbose) == true) {
|
|
114 |
fprintf(stderr, "ExternalFunctionCallback(wrapper): st-arg for %x is %x\n", *(unsigned int *)(args[i]), st_arg);
|
|
115 |
}
|
|
116 |
__ArrayInstPtr(st_argVector)->a_element[i] = st_arg; __STORE(st_argVector, st_arg);
|
|
117 |
}
|
|
118 |
|
|
119 |
/* the action ... */
|
|
120 |
st_actionVector = @global(ExternalFunctionCallback:CallBackRegistry);
|
|
121 |
if (st_actionVector != nil) {
|
|
122 |
OBJ cls = __Class(st_actionVector);
|
|
123 |
|
|
124 |
if ((cls == Array) || (cls==WeakArray)) {
|
|
125 |
actionIndex += /* nInstVars */ __intVal(__ClassInstPtr(cls)->c_ninstvars);
|
10607
|
126 |
|
10609
|
127 |
if (__arraySize(st_actionVector) <= actionIndex) {
|
|
128 |
st_callBack = __ArrayInstPtr(st_actionVector)->a_element[actionIndex-1];
|
|
129 |
}
|
|
130 |
}
|
|
131 |
}
|
|
132 |
if (st_callBack == nil) {
|
|
133 |
if (@global(ExternalFunctionCallback:Verbose) == true) {
|
|
134 |
fprintf(stderr, "ExternalFunctionCallback(wrapper): ignored nil callback\n");
|
|
135 |
}
|
|
136 |
*(void **)resp = 0;
|
|
137 |
return;
|
|
138 |
}
|
|
139 |
|
|
140 |
{
|
|
141 |
static struct inlineCache value_snd = _DUMMYILC1;
|
|
142 |
|
|
143 |
if (@global(ExternalFunctionCallback:Verbose) == true) {
|
|
144 |
fprintf(stderr, "ExternalFunctionCallback(wrapper): sending value: to %x..\n", st_callBack);
|
|
145 |
}
|
|
146 |
st_result = _SEND1(st_callBack, @symbol(value:), nil, &value_snd, st_argVector);
|
|
147 |
if (@global(ExternalFunctionCallback:Verbose) == true) {
|
|
148 |
fprintf(stderr, "ExternalFunctionCallback(wrapper): result is %x\n", st_result);
|
|
149 |
}
|
|
150 |
}
|
|
151 |
|
|
152 |
retType = cif->rtype;
|
|
153 |
|
|
154 |
if (st_result == true) {
|
|
155 |
sintResult = uintResult = 1;
|
|
156 |
} else if (st_result == false) {
|
|
157 |
sintResult = uintResult = 0;
|
|
158 |
} else if (st_result == nil) {
|
|
159 |
sintResult = uintResult = 0;
|
|
160 |
} else {
|
|
161 |
sintResult = __signedLongIntVal(st_result);
|
|
162 |
uintResult = __unsignedLongIntVal(st_result);
|
|
163 |
}
|
|
164 |
|
|
165 |
if (retType == __get_ffi_type_sint()) {
|
|
166 |
*(int *)resp = sintResult;
|
|
167 |
} else if (retType == __get_ffi_type_uint()) {
|
|
168 |
*(int *)resp = uintResult;
|
|
169 |
} else if (retType == __get_ffi_type_uint8()) {
|
|
170 |
*(unsigned char *)resp = uintResult;
|
|
171 |
} else if (retType == __get_ffi_type_sint8()) {
|
|
172 |
*(char *)resp = sintResult;
|
|
173 |
} else if (retType == __get_ffi_type_uint16()) {
|
|
174 |
*(unsigned short *)resp = uintResult;
|
|
175 |
} else if (retType == __get_ffi_type_sint16()) {
|
|
176 |
*(short *)resp = sintResult;
|
|
177 |
} else if (retType == __get_ffi_type_uint32()) {
|
|
178 |
*(int *)resp = uintResult;
|
|
179 |
} else if (retType == __get_ffi_type_sint32()) {
|
|
180 |
*(int *)resp = sintResult;
|
|
181 |
} else if (retType == __get_ffi_type_float()) {
|
|
182 |
if (__isFloat(st_result)) {
|
|
183 |
*(float *)resp = (float)__floatVal(st_result);
|
|
184 |
} else {
|
|
185 |
if (__isShortFloat(st_result)) {
|
|
186 |
*(float *)resp = __shortFloatVal(st_result);
|
|
187 |
} else {
|
|
188 |
*(float *)resp = (float)sintResult;
|
|
189 |
}
|
|
190 |
}
|
|
191 |
} else if (retType == __get_ffi_type_double()) {
|
|
192 |
if (__isFloat(st_result)) {
|
|
193 |
*(double *)resp = __floatVal(st_result);
|
|
194 |
} else {
|
|
195 |
if (__isShortFloat(st_result)) {
|
|
196 |
*(double *)resp = (double)__shortFloatVal(st_result);
|
|
197 |
} else {
|
|
198 |
*(double *)resp = (double)sintResult;
|
|
199 |
}
|
|
200 |
}
|
|
201 |
} else if (retType == __get_ffi_type_pointer()) {
|
|
202 |
*(void **)resp = (void *)__externalAddressVal( st_result );
|
|
203 |
} else {
|
|
204 |
if (@global(ExternalFunctionCallback:Verbose) == true) {
|
|
205 |
fprintf(stderr, "ExternalFunctionCallback(wrapper): invalid result type %d\n", retType, i);
|
|
206 |
}
|
|
207 |
*(void **)resp = 0;
|
|
208 |
}
|
10607
|
209 |
}
|
|
210 |
|
|
211 |
void
|
10609
|
212 |
ExternalFunctionCallback__test_call_closure(INTFUNC f)
|
10607
|
213 |
{
|
|
214 |
int result = 0;
|
|
215 |
|
|
216 |
printf("doCall_closure: calling closure %x(123)...\n", f);
|
|
217 |
result = (*f)(123);
|
|
218 |
printf("doCall_closure: back; result is %x...\n", result);
|
|
219 |
}
|
|
220 |
|
|
221 |
%}
|
|
222 |
! !
|
|
223 |
|
10609
|
224 |
!ExternalFunctionCallback class methodsFor:'documentation'!
|
|
225 |
|
|
226 |
copyright
|
|
227 |
"
|
|
228 |
COPYRIGHT (c) 2007 by eXept Software AG
|
|
229 |
All Rights Reserved
|
|
230 |
|
|
231 |
This software is furnished under a license and may be used
|
|
232 |
only in accordance with the terms of that license and with the
|
|
233 |
inclusion of the above copyright notice. This software may not
|
|
234 |
be provided or otherwise made available to, or used by, any
|
|
235 |
other person. No title to or ownership of the software is
|
|
236 |
hereby transferred.
|
|
237 |
"
|
|
238 |
!
|
|
239 |
|
|
240 |
documentation
|
|
241 |
"
|
|
242 |
an ExternalFunctionCallback wraps a block into a C-callable function;
|
|
243 |
i.e. it creates a closure, which as seen from C-code looks like an ordinary
|
|
244 |
function pointer, but when invoked evaluates a smalltalk block.
|
|
245 |
|
|
246 |
[author:]
|
|
247 |
Claus Gittinger
|
|
248 |
"
|
|
249 |
!
|
10607
|
250 |
|
|
251 |
examples
|
|
252 |
"
|
|
253 |
|cb|
|
|
254 |
|
|
255 |
cb := ExternalFunctionCallback new.
|
|
256 |
cb returnType:#bool argumentTypes:#(uint).
|
10609
|
257 |
cb action:[:args | Transcript showCR:args. true].
|
10607
|
258 |
cb generateClosure.
|
|
259 |
|
10609
|
260 |
cb address. 'can be passed to C'.
|
|
261 |
|
|
262 |
ExternalFunctionCallback testCall:cb withArgument:123.
|
|
263 |
cb release
|
10607
|
264 |
"
|
|
265 |
! !
|
|
266 |
|
10609
|
267 |
!ExternalFunctionCallback class methodsFor:'helpers'!
|
|
268 |
|
|
269 |
closureIndexFor:aCallBack
|
|
270 |
CallBackRegistry isNil ifTrue:[
|
|
271 |
CallBackRegistry := WeakArray with:aCallBack.
|
|
272 |
] ifFalse:[
|
|
273 |
CallBackRegistry := CallBackRegistry copyWith:aCallBack.
|
|
274 |
].
|
|
275 |
^ CallBackRegistry size.
|
|
276 |
!
|
|
277 |
|
|
278 |
testCall:aCallback withArgument:arg
|
|
279 |
%{
|
|
280 |
INTFUNC f = __externalAddressVal(aCallback);
|
|
281 |
INT result;
|
|
282 |
|
|
283 |
fprintf(stderr, "calling callBack %x(%d)\n", f, __intVal(arg));
|
|
284 |
result = (*f)(__intVal(arg));
|
|
285 |
fprintf(stderr, "result from callBack is %x\n", result);
|
|
286 |
%}
|
|
287 |
! !
|
|
288 |
|
10607
|
289 |
!ExternalFunctionCallback methodsFor:'accessing'!
|
|
290 |
|
10609
|
291 |
action:aOneArgBlock
|
|
292 |
action := aOneArgBlock.
|
|
293 |
! !
|
|
294 |
|
|
295 |
!ExternalFunctionCallback methodsFor:'callback'!
|
|
296 |
|
|
297 |
value:argList
|
|
298 |
"because this is evaluated from C, we probably should not block or abort or do
|
|
299 |
any other things which confuse C
|
|
300 |
(its probably a good idea to write something into a queue here)"
|
|
301 |
|
|
302 |
self halt.
|
|
303 |
action notNil ifTrue:[
|
|
304 |
^ action valueWithArguments:argList
|
|
305 |
].
|
|
306 |
^ nil
|
10607
|
307 |
! !
|
|
308 |
|
|
309 |
!ExternalFunctionCallback methodsFor:'generation'!
|
|
310 |
|
|
311 |
address
|
|
312 |
self isValid ifFalse:[
|
|
313 |
self generate
|
|
314 |
].
|
|
315 |
^ super address
|
|
316 |
|
|
317 |
"Created: / 11-06-2007 / 15:53:00 / cg"
|
|
318 |
!
|
|
319 |
|
|
320 |
generate
|
|
321 |
|code|
|
|
322 |
|
|
323 |
code := nil
|
|
324 |
|
|
325 |
"Created: / 11-06-2007 / 14:50:57 / cg"
|
|
326 |
!
|
|
327 |
|
|
328 |
generate0
|
|
329 |
|code|
|
|
330 |
|
|
331 |
code := #[
|
|
332 |
"/ mov ecx, closureIndex
|
|
333 |
16rB9
|
|
334 |
16r00 16r00 16r00 16r01
|
|
335 |
"/ mov eax, doClosureC
|
|
336 |
16rB8
|
|
337 |
16r00 16r00 16r00 16r02
|
|
338 |
"/ call *eax
|
|
339 |
16rFF 16rD0
|
|
340 |
"/ ret
|
|
341 |
16rC3
|
|
342 |
].
|
|
343 |
|
|
344 |
self allocateBytes:(code size).
|
|
345 |
|
|
346 |
"Created: / 11-06-2007 / 15:29:33 / cg"
|
|
347 |
! !
|
|
348 |
|
|
349 |
!ExternalFunctionCallback methodsFor:'private-accessing'!
|
|
350 |
|
|
351 |
returnType:aReturnType argumentTypes:argTypes
|
|
352 |
returnType := aReturnType.
|
|
353 |
argumentTypes := argTypes.
|
|
354 |
|
|
355 |
"Created: / 11-06-2007 / 15:52:01 / cg"
|
|
356 |
! !
|
|
357 |
|
10609
|
358 |
!ExternalFunctionCallback methodsFor:'private-debugging'!
|
|
359 |
|
|
360 |
debugCall:args
|
|
361 |
self halt.
|
|
362 |
^ nil
|
|
363 |
! !
|
|
364 |
|
10607
|
365 |
!ExternalFunctionCallback methodsFor:'private-generation'!
|
|
366 |
|
|
367 |
generateClosure
|
10609
|
368 |
|argTypeSymbols returnTypeSymbol failureCode failureInfo
|
|
369 |
callTypeNumber returnValueClass argValueClass callBackIndex|
|
10607
|
370 |
|
|
371 |
argTypeSymbols := argumentTypes.
|
|
372 |
returnTypeSymbol := returnType.
|
10609
|
373 |
callBackIndex := self class closureIndexFor:self.
|
|
374 |
%{
|
10607
|
375 |
#ifdef HAVE_FFI
|
10609
|
376 |
ffi_cif *pcif;
|
10607
|
377 |
ffi_type *__returnType = NULL;
|
|
378 |
static int null = 0;
|
|
379 |
int i;
|
|
380 |
ffi_abi __callType = FFI_DEFAULT_ABI;
|
|
381 |
int __numArgsWanted;
|
10609
|
382 |
struct closurePlusCIF {
|
|
383 |
ffi_closure closure;
|
|
384 |
ffi_cif cif;
|
|
385 |
ffi_type *argTypes[MAX_ARGS];
|
|
386 |
} *closurePlusCIFp;
|
10607
|
387 |
ffi_closure *pcl;
|
10609
|
388 |
ffi_cif *cif;
|
|
389 |
ffi_type **argTypePtrs;
|
|
390 |
|
|
391 |
closurePlusCIFp = (struct closurePlusCIF *) malloc(sizeof(struct closurePlusCIF));
|
|
392 |
cif = &(closurePlusCIFp->cif);
|
|
393 |
argTypePtrs = closurePlusCIFp->argTypes;
|
|
394 |
pcl = &(closurePlusCIFp->closure);
|
10607
|
395 |
|
|
396 |
#define __FAIL__(fcode) \
|
|
397 |
{ \
|
10609
|
398 |
failureCode = fcode; free(closurePlusCIFp); goto getOutOfHere; \
|
10607
|
399 |
}
|
|
400 |
|
|
401 |
if (argTypeSymbols == nil) {
|
|
402 |
__numArgsWanted = 0;
|
|
403 |
} else if (__isArray(argTypeSymbols)) {
|
|
404 |
__numArgsWanted = __arraySize(argTypeSymbols);
|
|
405 |
} else {
|
|
406 |
__FAIL__(@symbol(BadArgumentTypeVector))
|
|
407 |
}
|
|
408 |
|
|
409 |
if (__numArgsWanted > MAX_ARGS) {
|
|
410 |
__FAIL__(@symbol(TooManyArguments))
|
|
411 |
}
|
|
412 |
|
|
413 |
/*
|
|
414 |
* validate the return type
|
|
415 |
*/
|
|
416 |
if (returnTypeSymbol == @symbol(voidPointer)) {
|
|
417 |
returnTypeSymbol = @symbol(handle);
|
|
418 |
}
|
|
419 |
|
|
420 |
if (returnTypeSymbol == @symbol(int)) {
|
|
421 |
__returnType = __get_ffi_type_sint();
|
|
422 |
} else if (returnTypeSymbol == @symbol(uint)) {
|
|
423 |
__returnType = __get_ffi_type_uint();
|
|
424 |
} else if (returnTypeSymbol == @symbol(uint8)) {
|
|
425 |
__returnType = __get_ffi_type_uint8();
|
|
426 |
} else if (returnTypeSymbol == @symbol(uint16)) {
|
|
427 |
__returnType = __get_ffi_type_uint16();
|
|
428 |
} else if (returnTypeSymbol == @symbol(uint32)) {
|
|
429 |
__returnType = __get_ffi_type_uint32();
|
|
430 |
} else if (returnTypeSymbol == @symbol(uint64)) {
|
|
431 |
__returnType = __get_ffi_type_uint64();
|
|
432 |
|
|
433 |
} else if (returnTypeSymbol == @symbol(sint)) {
|
|
434 |
__returnType = __get_ffi_type_sint();
|
|
435 |
} else if (returnTypeSymbol == @symbol(sint8)) {
|
|
436 |
__returnType = __get_ffi_type_sint8();
|
|
437 |
} else if (returnTypeSymbol == @symbol(sint16)) {
|
|
438 |
__returnType = __get_ffi_type_sint16();
|
|
439 |
} else if (returnTypeSymbol == @symbol(sint32)) {
|
|
440 |
__returnType = __get_ffi_type_sint32();
|
|
441 |
} else if (returnTypeSymbol == @symbol(sint64)) {
|
|
442 |
__returnType = __get_ffi_type_sint64();
|
|
443 |
|
|
444 |
} else if (returnTypeSymbol == @symbol(long)) {
|
|
445 |
if (sizeof(long) == 4) {
|
|
446 |
returnTypeSymbol = @symbol(sint32);
|
|
447 |
__returnType = __get_ffi_type_sint32();
|
|
448 |
} else if (sizeof(long) == 8) {
|
|
449 |
returnTypeSymbol = @symbol(sint64);
|
|
450 |
__returnType = __get_ffi_type_sint64();
|
|
451 |
} else {
|
|
452 |
__FAIL__(@symbol(UnknownReturnType))
|
|
453 |
}
|
|
454 |
|
|
455 |
} else if (returnTypeSymbol == @symbol(ulong)) {
|
|
456 |
if (sizeof(long) == 4) {
|
|
457 |
returnTypeSymbol = @symbol(uint32);
|
|
458 |
__returnType = __get_ffi_type_uint32();
|
|
459 |
}else if (sizeof(long) == 8) {
|
|
460 |
returnTypeSymbol = @symbol(uint64);
|
|
461 |
__returnType = __get_ffi_type_uint64();
|
|
462 |
} else {
|
|
463 |
__FAIL__(@symbol(UnknownReturnType))
|
|
464 |
}
|
|
465 |
|
|
466 |
} else if (returnTypeSymbol == @symbol(bool)) {
|
|
467 |
__returnType = __get_ffi_type_uint();
|
|
468 |
|
|
469 |
} else if (returnTypeSymbol == @symbol(float)) {
|
|
470 |
__returnType = __get_ffi_type_float();
|
|
471 |
} else if (returnTypeSymbol == @symbol(double)) {
|
|
472 |
__returnType = __get_ffi_type_double();
|
|
473 |
|
|
474 |
} else if (returnTypeSymbol == @symbol(void)) {
|
|
475 |
__returnType = __get_ffi_type_void();
|
|
476 |
} else if ((returnTypeSymbol == @symbol(pointer))
|
|
477 |
|| (returnTypeSymbol == @symbol(handle))
|
|
478 |
|| (returnTypeSymbol == @symbol(charPointer))
|
|
479 |
|| (returnTypeSymbol == @symbol(bytePointer))
|
|
480 |
|| (returnTypeSymbol == @symbol(floatPointer))
|
|
481 |
|| (returnTypeSymbol == @symbol(doublePointer))
|
|
482 |
|| (returnTypeSymbol == @symbol(intPointer))
|
|
483 |
|| (returnTypeSymbol == @symbol(shortPointer))
|
|
484 |
|| (returnTypeSymbol == @symbol(wcharPointer))) {
|
|
485 |
__returnType = __get_ffi_type_pointer();
|
|
486 |
} else {
|
|
487 |
if (__isSymbol(returnTypeSymbol)
|
|
488 |
&& ((returnValueClass = __GLOBAL_GET(returnTypeSymbol)) != nil)) {
|
|
489 |
if (! __isBehaviorLike(returnValueClass)) {
|
|
490 |
__FAIL__(@symbol(NonBehaviorReturnType))
|
|
491 |
}
|
|
492 |
if (! __qIsSubclassOfExternalAddress(returnValueClass)) {
|
|
493 |
__FAIL__(@symbol(NonExternalAddressReturnType))
|
|
494 |
}
|
|
495 |
__returnType = __get_ffi_type_pointer();
|
|
496 |
returnTypeSymbol = @symbol(pointer);
|
|
497 |
} else {
|
|
498 |
__FAIL__(@symbol(UnknownReturnType))
|
|
499 |
}
|
|
500 |
}
|
|
501 |
|
|
502 |
/*
|
|
503 |
* setup arg-buffers
|
|
504 |
*/
|
|
505 |
for (i=0; i<__numArgsWanted; i++) {
|
|
506 |
ffi_type *thisType;
|
|
507 |
void *argValuePtr;
|
|
508 |
OBJ typeSymbol;
|
|
509 |
|
|
510 |
failureInfo = __mkSmallInteger(i+1); /* in case there is one */
|
|
511 |
|
|
512 |
typeSymbol = __ArrayInstPtr(argTypeSymbols)->a_element[i];
|
|
513 |
|
|
514 |
if (typeSymbol == @symbol(handle)) {
|
|
515 |
typeSymbol = @symbol(pointer);
|
|
516 |
} else if (typeSymbol == @symbol(voidPointer)) {
|
|
517 |
typeSymbol = @symbol(pointer);
|
|
518 |
}
|
|
519 |
|
|
520 |
if (typeSymbol == @symbol(long)) {
|
|
521 |
if (sizeof(long) == sizeof(int)) {
|
|
522 |
typeSymbol = @symbol(sint);
|
|
523 |
} else {
|
|
524 |
if (sizeof(long) == 4) {
|
|
525 |
typeSymbol = @symbol(sint32);
|
|
526 |
} else if (sizeof(long) == 8) {
|
|
527 |
typeSymbol = @symbol(sint64);
|
|
528 |
}
|
|
529 |
}
|
|
530 |
}
|
|
531 |
if (typeSymbol == @symbol(ulong)) {
|
|
532 |
if (sizeof(unsigned long) == sizeof(unsigned int)) {
|
|
533 |
typeSymbol = @symbol(uint);
|
|
534 |
} else {
|
|
535 |
if (sizeof(long) == 4) {
|
|
536 |
typeSymbol = @symbol(uint32);
|
|
537 |
} else if (sizeof(long) == 8) {
|
|
538 |
typeSymbol = @symbol(uint64);
|
|
539 |
}
|
|
540 |
}
|
|
541 |
}
|
|
542 |
|
|
543 |
if (typeSymbol == @symbol(int)) {
|
|
544 |
thisType = __get_ffi_type_sint();
|
|
545 |
} else if (typeSymbol == @symbol(uint)) {
|
|
546 |
thisType = __get_ffi_type_uint();
|
|
547 |
} else if (typeSymbol == @symbol(uint8)) {
|
|
548 |
thisType = __get_ffi_type_uint8();
|
|
549 |
} else if (typeSymbol == @symbol(sint8)) {
|
|
550 |
thisType = __get_ffi_type_sint8();
|
|
551 |
} else if (typeSymbol == @symbol(uint16)) {
|
|
552 |
thisType = __get_ffi_type_uint16();
|
|
553 |
} else if (typeSymbol == @symbol(sint16)) {
|
|
554 |
thisType = __get_ffi_type_sint16();
|
|
555 |
} else if ((typeSymbol == @symbol(uint32)) || (typeSymbol == @symbol(sint32))) {
|
|
556 |
thisType = __get_ffi_type_uint32();
|
|
557 |
} else if (typeSymbol == @symbol(float)) {
|
|
558 |
thisType = __get_ffi_type_float();
|
|
559 |
} else if (typeSymbol == @symbol(double)) {
|
|
560 |
thisType = __get_ffi_type_double();
|
|
561 |
} else if (typeSymbol == @symbol(void)) {
|
|
562 |
thisType = __get_ffi_type_void();
|
|
563 |
} else if (typeSymbol == @symbol(charPointer)) {
|
|
564 |
thisType = __get_ffi_type_pointer();
|
|
565 |
} else if (typeSymbol == @symbol(floatPointer)) {
|
|
566 |
thisType = __get_ffi_type_pointer();
|
|
567 |
} else if (typeSymbol == @symbol(doublePointer)) {
|
|
568 |
thisType = __get_ffi_type_pointer();
|
|
569 |
} else if (typeSymbol == @symbol(pointer)) {
|
|
570 |
commonPointerTypeArg: ;
|
|
571 |
thisType = __get_ffi_type_pointer();
|
|
572 |
} else if (typeSymbol == @symbol(bool)) {
|
|
573 |
thisType = __get_ffi_type_uint();
|
|
574 |
} else if (__isSymbol(typeSymbol)
|
|
575 |
&& ((argValueClass = __GLOBAL_GET(typeSymbol)) != nil)) {
|
|
576 |
if (! __isBehaviorLike(argValueClass)) {
|
|
577 |
__FAIL__(@symbol(NonBehaviorArgumentType))
|
|
578 |
}
|
|
579 |
if (! __qIsSubclassOfExternalAddress(argValueClass)) {
|
|
580 |
__FAIL__(@symbol(NonExternalAddressArgumentType))
|
|
581 |
}
|
|
582 |
goto commonPointerTypeArg; /* sorry */
|
|
583 |
} else {
|
|
584 |
__FAIL__(@symbol(UnknownArgumentType))
|
|
585 |
}
|
|
586 |
|
10609
|
587 |
closurePlusCIFp->argTypes[i] = thisType;
|
10607
|
588 |
}
|
|
589 |
failureInfo = nil;
|
|
590 |
|
|
591 |
__callType = FFI_DEFAULT_ABI;
|
|
592 |
|
|
593 |
if (callTypeNumber != nil) {
|
|
594 |
#ifdef CALLTYPE_FFI_STDCALL
|
|
595 |
if (callTypeNumber == @global(ExternalLibraryFunction:CALLTYPE_API)) {
|
|
596 |
__callType = CALLTYPE_FFI_STDCALL;
|
|
597 |
}
|
|
598 |
#endif
|
|
599 |
#ifdef CALLTYPE_FFI_V8
|
|
600 |
if (callTypeNumber == @global(ExternalLibraryFunction:CALLTYPE_V8)) {
|
|
601 |
__callType = CALLTYPE_FFI_V8;
|
|
602 |
}
|
|
603 |
#endif
|
|
604 |
#ifdef CALLTYPE_FFI_V9
|
|
605 |
if (callTypeNumber == @global(ExternalLibraryFunction:CALLTYPE_V9)) {
|
|
606 |
__callType = CALLTYPE_FFI_V9;
|
|
607 |
}
|
|
608 |
#endif
|
|
609 |
#ifdef CALLTYPE_FFI_UNIX64
|
|
610 |
if (callTypeNumber == @global(ExternalLibraryFunction:CALLTYPE_UNIX64)) {
|
|
611 |
__callType = CALLTYPE_FFI_UNIX64;
|
|
612 |
}
|
|
613 |
#endif
|
|
614 |
}
|
|
615 |
|
10609
|
616 |
if (@global(ExternalFunctionCallback:Verbose) == true) {
|
|
617 |
printf("prep_cif cif-ptr=%x\n", cif);
|
|
618 |
}
|
|
619 |
|
|
620 |
if (ffi_prep_cif(cif, __callType, __numArgsWanted, __returnType, argTypePtrs) != FFI_OK) {
|
10607
|
621 |
__FAIL__(@symbol(FFIPrepareFailed))
|
|
622 |
}
|
10609
|
623 |
|
|
624 |
if (@global(ExternalFunctionCallback:Verbose) == true) {
|
|
625 |
printf("closure is 0x%x (%d bytes)\n", pcl, sizeof(ffi_closure));
|
|
626 |
printf("index is %d\n", __intVal(callBackIndex));
|
|
627 |
}
|
|
628 |
if (ffi_prep_closure(pcl, cif, ExternalFunctionCallback__closure_wrapper_fn, (void *)(__intVal(callBackIndex)) /* userdata */) != FFI_OK) {
|
10607
|
629 |
__FAIL__(@symbol(FFIPrepareClosureFailed))
|
|
630 |
}
|
10609
|
631 |
if (@global(ExternalFunctionCallback:Verbose) == true) {
|
|
632 |
printf("pcl->cif is 0x%x\n", pcl->cif);
|
|
633 |
printf("pcl->fun is 0x%x\n", pcl->fun);
|
|
634 |
printf("pcl code at %x is:\n", pcl);
|
|
635 |
printf(" %02x %02x %02x %02x\n", ((unsigned char *)pcl)[0],((unsigned char *)pcl)[1],((unsigned char *)pcl)[2],((unsigned char *)pcl)[3]);
|
|
636 |
printf(" %02x %02x %02x %02x\n", ((unsigned char *)pcl)[4],((unsigned char *)pcl)[5],((unsigned char *)pcl)[6],((unsigned char *)pcl)[7]);
|
|
637 |
printf(" %02x %02x %02x %02x\n", ((unsigned char *)pcl)[8],((unsigned char *)pcl)[9],((unsigned char *)pcl)[10],((unsigned char *)pcl)[11]);
|
|
638 |
printf(" %02x %02x %02x %02x\n", ((unsigned char *)pcl)[12],((unsigned char *)pcl)[13],((unsigned char *)pcl)[14],((unsigned char *)pcl)[15]);
|
|
639 |
}
|
|
640 |
__INST(address_) = pcl;
|
|
641 |
|
|
642 |
#if 0
|
|
643 |
ExternalFunctionCallback__test_call_closure((INTFUNC)pcl);
|
10607
|
644 |
#endif
|
|
645 |
|
|
646 |
#else /* no FFI support */
|
|
647 |
__FAIL__(@symbol(FFINotSupported));
|
|
648 |
#endif /* HAVE_FFI */
|
|
649 |
getOutOfHere: ;
|
|
650 |
%}.
|
|
651 |
failureCode notNil ifTrue:[
|
|
652 |
self primitiveFailed:(failureCode->failureInfo). "see failureCode and failureInfo for details"
|
|
653 |
^ nil
|
|
654 |
].
|
|
655 |
|
|
656 |
"Created: / 11-06-2007 / 21:53:02 / cg"
|
|
657 |
! !
|
10609
|
658 |
|
|
659 |
!ExternalFunctionCallback methodsFor:'private-releasing'!
|
|
660 |
|
|
661 |
release
|
|
662 |
|idx|
|
|
663 |
|
|
664 |
idx := CallBackRegistry identityIndexOf:self.
|
|
665 |
CallBackRegistry at:idx put:nil.
|
|
666 |
%{
|
|
667 |
ffi_closure *pcl = (ffi_closure *)__INST(address_);
|
|
668 |
|
|
669 |
__INST(address_) = 0;
|
|
670 |
if (pcl) {
|
|
671 |
free(pcl);
|
|
672 |
}
|
|
673 |
%}.
|
|
674 |
self invalidateReference.
|
|
675 |
|
|
676 |
! !
|
|
677 |
|
|
678 |
!ExternalFunctionCallback class methodsFor:'documentation'!
|
|
679 |
|
|
680 |
version
|
|
681 |
^ '$Header: /cvs/stx/stx/libbasic/ExternalFunctionCallback.st,v 1.2 2007-06-13 21:13:25 cg Exp $'
|
|
682 |
! !
|