--- a/ExternalLibraryFunction.st Wed May 03 00:13:59 2006 +0200
+++ b/ExternalLibraryFunction.st Fri May 05 11:40:18 2006 +0200
@@ -212,715 +212,6 @@
!ExternalLibraryFunction methodsFor:'private'!
-invokeFFIWithArguments:arguments
- |argTypeSymbols returnTypeSymbol failureCode|
-
- argumentTypes notNil ifTrue:[
- argTypeSymbols := argumentTypes collect:[:argType | self ffiTypeSymbolForType:argType].
- ].
- returnTypeSymbol := self ffiTypeSymbolForType:returnType.
-
-%{ /* UNLIMITEDSTACK */
-#ifdef HAVE_FFI
- ffi_cif __cif;
- ffi_type *__argTypes[MAX_ARGS];
- ffi_type *__returnType = NULL;
- union u {
- int iVal;
- float fVal;
- double dVal;
- void *pointerVal;
- };
- union u __argValues[MAX_ARGS];
- union u __returnValue;
- void *__argValuePointers[MAX_ARGS];
- void *__returnValuePointer;
- int __numArgs;
- static int null = 0;
- int i;
- ffi_abi __callType = FFI_DEFAULT_ABI;
-
- if (arguments == nil) {
- __numArgs = 0;
- if (argTypeSymbols != nil) {
- if (! __isArray(argTypeSymbols)
- || (__arraySize(argTypeSymbols) != __numArgs)) {
- failureCode = @symbol(ArgumentCountMismatch);
- goto error;
- }
- }
- } else {
- if (! __isArray(arguments)
- || ! __isArray(argTypeSymbols)
- || (__arraySize(argTypeSymbols) != (__numArgs = __arraySize(arguments)))) {
- failureCode = @symbol(ArgumentCountMismatch);
- goto error;
- }
- }
- if (__numArgs > MAX_ARGS) {
- failureCode = @symbol(TooManyArguments);
- goto error;
- }
-
- /*
- * validate the return type
- */
- __returnValuePointer = &__returnValue;
- if (returnTypeSymbol == @symbol(int)) {
- __returnType = __get_ffi_type_sint();
- } else if (returnTypeSymbol == @symbol(uint)) {
- __returnType = __get_ffi_type_uint();
- } else if (returnTypeSymbol == @symbol(long)) {
- if (sizeof(long) == 4) {
- __returnType = __get_ffi_type_sint32();
- } else if (sizeof(long) == 8) {
- __returnType = __get_ffi_type_sint64();
- } else {
- failureCode = @symbol(UnknownReturnType);
- goto error;
- }
- } else if (returnTypeSymbol == @symbol(ulong)) {
- if (sizeof(long) == 4) {
- __returnType = __get_ffi_type_uint32();
- }else if (sizeof(long) == 8) {
- __returnType = __get_ffi_type_uint64();
- } else {
- failureCode = @symbol(UnknownReturnType);
- goto error;
- }
- } else if (returnTypeSymbol == @symbol(boolean)) {
- __returnType = __get_ffi_type_uint();
- } else if (returnTypeSymbol == @symbol(uint8)) {
- __returnType = __get_ffi_type_uint8();
- } else if (returnTypeSymbol == @symbol(sint8)) {
- __returnType = __get_ffi_type_sint8();
- } else if (returnTypeSymbol == @symbol(uint16)) {
- __returnType = __get_ffi_type_uint16();
- } else if (returnTypeSymbol == @symbol(sint16)) {
- __returnType = __get_ffi_type_sint16();
- } else if (returnTypeSymbol == @symbol(float)) {
- __returnType = __get_ffi_type_float();
- } else if (returnTypeSymbol == @symbol(double)) {
- __returnType = __get_ffi_type_double();
- } else if (returnTypeSymbol == @symbol(void)) {
- __returnType = __get_ffi_type_void();
- __returnValuePointer = NULL;
- } else if (returnTypeSymbol == @symbol(pointer)) {
- __returnType = __get_ffi_type_pointer();
- } else {
- failureCode = @symbol(UnknownReturnType);
- goto error;
- }
-
- /*
- * validate all arg types and setup arg-buffers
- */
- for (i=0; i<__numArgs; i++) {
- ffi_type *thisType;
- void *argValuePtr;
- OBJ typeSymbol;
- OBJ arg;
-
- typeSymbol = __ArrayInstPtr(argTypeSymbols)->a_element[i];
- arg = __ArrayInstPtr(arguments)->a_element[i];
-
- if (typeSymbol == @symbol(long)) {
- if (sizeof(long) == sizeof(int)) {
- typeSymbol = @symbol(sint);
- } else {
- if (sizeof(long) == 4) {
- typeSymbol = @symbol(sint32);
- } else if (sizeof(long) == 8) {
- typeSymbol = @symbol(sint64);
- }
- }
- }
- if (typeSymbol == @symbol(ulong)) {
- if (sizeof(unsigned long) == sizeof(unsigned int)) {
- typeSymbol = @symbol(uint);
- } else {
- if (sizeof(long) == 4) {
- typeSymbol = @symbol(uint32);
- } else if (sizeof(long) == 8) {
- typeSymbol = @symbol(uint64);
- }
- }
- }
-
- if (typeSymbol == @symbol(int)) {
- thisType = __get_ffi_type_sint();
- if (__isSmallInteger(arg)) {
- __argValues[i].iVal = __intVal(arg);
- } else {
- __argValues[i].iVal = __signedLongIntVal(arg);
- if (__argValues[i].iVal == 0) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- }
- argValuePtr = &(__argValues[i].iVal);
- } else if (typeSymbol == @symbol(uint)) {
- thisType = __get_ffi_type_uint();
-
- if (__isSmallInteger(arg)) {
- __argValues[i].iVal = __intVal(arg);
- } else {
- __argValues[i].iVal = __unsignedLongIntVal(arg);
- if (__argValues[i].iVal == 0) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- }
- argValuePtr = &(__argValues[i].iVal);
- } else if (typeSymbol == @symbol(uint8)) {
- thisType = __get_ffi_type_uint8();
- if (! __isSmallInteger(arg)) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- __argValues[i].iVal = __intVal(arg);
- if (((unsigned)(__argValues[i].iVal)) > 0xFF) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- argValuePtr = &(__argValues[i].iVal);
- } else if (typeSymbol == @symbol(sint8)) {
- thisType = __get_ffi_type_sint8();
- if (! __isSmallInteger(arg)) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- __argValues[i].iVal = __intVal(arg);
- if (((__argValues[i].iVal) < -0x80) || ((__argValues[i].iVal) > 0x7F)) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- argValuePtr = &(__argValues[i].iVal);
- } else if (typeSymbol == @symbol(uint16)) {
- thisType = __get_ffi_type_uint16();
- if (! __isSmallInteger(arg)) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- __argValues[i].iVal = __intVal(arg);
- if (((unsigned)(__argValues[i].iVal)) > 0xFFFF) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- argValuePtr = &(__argValues[i].iVal);
- } else if (typeSymbol == @symbol(sint16)) {
- thisType = __get_ffi_type_sint16();
- if (! __isSmallInteger(arg)) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- __argValues[i].iVal = __intVal(arg);
- if (((__argValues[i].iVal) < -0x8000) || ((__argValues[i].iVal) > 0x7FFF)) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- argValuePtr = &(__argValues[i].iVal);
- } else if (typeSymbol == @symbol(float)) {
- thisType = __get_ffi_type_float();
- if (__isSmallInteger(arg)) {
- __argValues[i].fVal = (float)(__intVal(arg));
- } else if (__isFloat(arg)) {
- __argValues[i].fVal = (float)(__floatVal(arg));
- } else if (__isShortFloat(arg)) {
- __argValues[i].fVal = (float)(__shortFloatVal(arg));
- } else {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- argValuePtr = &(__argValues[i].fVal);
- } else if (typeSymbol == @symbol(double)) {
- thisType = __get_ffi_type_double();
- if (__isSmallInteger(arg)) {
- __argValues[i].dVal = (double)(__intVal(arg));
- } else if (__isFloat(arg)) {
- __argValues[i].dVal = (double)(__floatVal(arg));
- } else if (__isShortFloat(arg)) {
- __argValues[i].dVal = (double)(__shortFloatVal(arg));
- } else {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- argValuePtr = &(__argValues[i].dVal);
- } else if (typeSymbol == @symbol(void)) {
- thisType = __get_ffi_type_void();
- argValuePtr = &null;
- } else if (typeSymbol == @symbol(pointer)) {
- thisType = __get_ffi_type_pointer();
- if (__isExternalAddressLike(arg)) {
- __argValues[i].pointerVal = (void *)(__externalAddressVal(arg));
- } else if (__isExternalBytesLike(arg)) {
- __argValues[i].pointerVal = (void *)(__externalBytesVal(arg));
- } else if (__isByteArray(arg)) {
- __argValues[i].pointerVal = (void *)(__byteArrayVal(arg));
- } else if (__isFloatArray(arg)) {
- __argValues[i].pointerVal = (void *)(__FloatArrayInstPtr(arg)->f_element);
- } else if (__isDoubleArray(arg)) {
- __argValues[i].pointerVal = (void *)(__DoubleArrayInstPtr(arg)->d_element);
- } else if (__isString(arg) || __isSymbol(arg)) {
- __argValues[i].pointerVal = (void *)(__stringVal(arg));
- } else {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- argValuePtr = &(__argValues[i].pointerVal);;
- } else if (typeSymbol == @symbol(boolean)) {
- thisType = __get_ffi_type_uint();
-
- if (arg == true) {
- __argValues[i].iVal = 1;
- } else if (arg == false) {
- __argValues[i].iVal = 0;
- } else if (__isSmallInteger(arg)) {
- __argValues[i].iVal = __intVal(arg);
- } else {
- __argValues[i].iVal = __unsignedLongIntVal(arg);
- if (__argValues[i].iVal == 0) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- }
- argValuePtr = &(__argValues[i].iVal);
- } else {
- failureCode = @symbol(UnknownArgumentType);
- goto error;
- }
-
- __argTypes[i] = thisType;
- __argValuePointers[i] = argValuePtr;
- }
-
- __callType = FFI_DEFAULT_ABI;
-
-#ifdef CALLTYPE_FFI_STDCALL
- if ((__INST(callType) == @symbol(callTypeAPI))
- || (__INST(callType) == @symbol(WINAPI))
- || (__INST(callType) == @symbol(STDCALL))) {
- __callType = CALLTYPE_FFI_STDCALL;
- }
-#endif
-#ifdef CALLTYPE_FFI_V8
- if ((__INST(callType) == @symbol(callTypeV8))
- || (__INST(callType) == @symbol(V8))) {
- __callType = CALLTYPE_FFI_V8;
- }
-#endif
-#ifdef CALLTYPE_FFI_V9
- if ((__INST(callType) == @symbol(callTypeV9))
- || (__INST(callType) == @symbol(V9))) {
- __callType = CALLTYPE_FFI_V9;
- }
-#endif
-#ifdef CALLTYPE_FFI_UNIX64
- if ((__INST(callType) == @symbol(callTypeUnix64))
- || (__INST(callType) == @symbol(UNIX64))) {
- __callType = CALLTYPE_FFI_UNIX64;
- }
-#endif
-
- if (ffi_prep_cif(&__cif, __callType, __numArgs, __returnType, __argTypes) != FFI_OK) {
- failureCode = @symbol(FFIPrepareFailed);
- goto error;
- }
- ffi_call(&__cif, (VOIDFUNC)__INST(code_), __returnValuePointer, __argValuePointers);
-
- if ((returnTypeSymbol == @symbol(int))
- || (returnTypeSymbol == @symbol(int8))
- || (returnTypeSymbol == @symbol(int16))) {
- RETURN ( __MKINT(__returnValue.iVal) );
- }
- if ((returnTypeSymbol == @symbol(uint))
- || (returnTypeSymbol == @symbol(uint8))
- || (returnTypeSymbol == @symbol(uint16))) {
- RETURN ( __MKUINT(__returnValue.iVal) );
- }
- if (returnTypeSymbol == @symbol(boolean)) {
- RETURN ( __returnValue.iVal ? true : false );
- }
- if (returnTypeSymbol == @symbol(float)) {
- RETURN ( __MKFLOAT(__returnValue.fVal ));
- }
- if (returnTypeSymbol == @symbol(double)) {
- RETURN ( __MKFLOAT(__returnValue.dVal ));
- }
- if (returnTypeSymbol == @symbol(void)) {
- RETURN ( nil );
- }
- if (returnTypeSymbol == @symbol(pointer)) {
-printf("returnvalue: %x\n", __returnValue.pointerVal);
- RETURN ( __MKEXTERNALADDRESS(__returnValue.pointerVal) );
- }
- failureCode = @symbol(UnknownReturnType2);
-error: ;
-
-#else /* no FFI support */
- failureCode = @symbol(FFINotSupported);
-#endif /* HAVE_FFI */
-%}.
- failureCode notNil ifTrue:[
- self primitiveFailed
- ].
-!
-
-invokeVirtualFFIOn:instance withArguments:arguments
- |argTypeSymbols returnTypeSymbol failureCode|
-
- argumentTypes notNil ifTrue:[
- argTypeSymbols := argumentTypes collect:[:argType | self ffiTypeSymbolForType:argType].
- ].
- returnTypeSymbol := self ffiTypeSymbolForType:returnType.
-self halt:'unfinished'.
-
-%{ /* UNLIMITEDSTACK */
-#ifdef HAVE_FFI
- ffi_cif __cif;
- ffi_type *__argTypes[MAX_ARGS];
- ffi_type *__returnType = NULL;
- union u {
- int iVal;
- float fVal;
- double dVal;
- void *pointerVal;
- };
- union u __argValues[MAX_ARGS];
- union u __returnValue;
- void *__argValuePointers[MAX_ARGS];
- void *__returnValuePointer;
- int __numArgs;
- static int null = 0;
- int i;
- ffi_abi __callType = FFI_DEFAULT_ABI;
-
- if (arguments == nil) {
- __numArgs = 0;
- if (argTypeSymbols != nil) {
- if (! __isArray(argTypeSymbols)
- || (__arraySize(argTypeSymbols) != __numArgs)) {
- failureCode = @symbol(ArgumentCountMismatch);
- goto error;
- }
- }
- } else {
- if (! __isArray(arguments)
- || ! __isArray(argTypeSymbols)
- || (__arraySize(argTypeSymbols) != (__numArgs = __arraySize(arguments)))) {
- failureCode = @symbol(ArgumentCountMismatch);
- goto error;
- }
- }
- if (__numArgs > MAX_ARGS) {
- failureCode = @symbol(TooManyArguments);
- goto error;
- }
-
- /*
- * validate the return type
- */
- __returnValuePointer = &__returnValue;
- if (returnTypeSymbol == @symbol(int)) {
- __returnType = __get_ffi_type_sint();
- } else if (returnTypeSymbol == @symbol(uint)) {
- __returnType = __get_ffi_type_uint();
- } else if (returnTypeSymbol == @symbol(long)) {
- if (sizeof(long) == 4) {
- __returnType = __get_ffi_type_sint32();
- } else if (sizeof(long) == 8) {
- __returnType = __get_ffi_type_sint64();
- } else {
- failureCode = @symbol(UnknownReturnType);
- goto error;
- }
- } else if (returnTypeSymbol == @symbol(ulong)) {
- if (sizeof(long) == 4) {
- __returnType = __get_ffi_type_uint32();
- }else if (sizeof(long) == 8) {
- __returnType = __get_ffi_type_uint64();
- } else {
- failureCode = @symbol(UnknownReturnType);
- goto error;
- }
- } else if (returnTypeSymbol == @symbol(boolean)) {
- __returnType = __get_ffi_type_uint();
- } else if (returnTypeSymbol == @symbol(uint8)) {
- __returnType = __get_ffi_type_uint8();
- } else if (returnTypeSymbol == @symbol(sint8)) {
- __returnType = __get_ffi_type_sint8();
- } else if (returnTypeSymbol == @symbol(uint16)) {
- __returnType = __get_ffi_type_uint16();
- } else if (returnTypeSymbol == @symbol(sint16)) {
- __returnType = __get_ffi_type_sint16();
- } else if (returnTypeSymbol == @symbol(float)) {
- __returnType = __get_ffi_type_float();
- } else if (returnTypeSymbol == @symbol(double)) {
- __returnType = __get_ffi_type_double();
- } else if (returnTypeSymbol == @symbol(void)) {
- __returnType = __get_ffi_type_void();
- __returnValuePointer = NULL;
- } else if (returnTypeSymbol == @symbol(pointer)) {
- __returnType = __get_ffi_type_pointer();
- } else {
- failureCode = @symbol(UnknownReturnType);
- goto error;
- }
-
- /*
- * validate all arg types and setup arg-buffers
- */
- for (i=0; i<__numArgs; i++) {
- ffi_type *thisType;
- void *argValuePtr;
- OBJ typeSymbol;
- OBJ arg;
-
- typeSymbol = __ArrayInstPtr(argTypeSymbols)->a_element[i];
- arg = __ArrayInstPtr(arguments)->a_element[i];
-
- if (typeSymbol == @symbol(long)) {
- if (sizeof(long) == sizeof(int)) {
- typeSymbol = @symbol(sint);
- } else {
- if (sizeof(long) == 4) {
- typeSymbol = @symbol(sint32);
- } else if (sizeof(long) == 8) {
- typeSymbol = @symbol(sint64);
- }
- }
- }
- if (typeSymbol == @symbol(ulong)) {
- if (sizeof(unsigned long) == sizeof(unsigned int)) {
- typeSymbol = @symbol(uint);
- } else {
- if (sizeof(long) == 4) {
- typeSymbol = @symbol(uint32);
- } else if (sizeof(long) == 8) {
- typeSymbol = @symbol(uint64);
- }
- }
- }
-
- if (typeSymbol == @symbol(int)) {
- thisType = __get_ffi_type_sint();
- if (__isSmallInteger(arg)) {
- __argValues[i].iVal = __intVal(arg);
- } else {
- __argValues[i].iVal = __signedLongIntVal(arg);
- if (__argValues[i].iVal == 0) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- }
- argValuePtr = &(__argValues[i].iVal);
- } else if (typeSymbol == @symbol(uint)) {
- thisType = __get_ffi_type_uint();
-
- if (__isSmallInteger(arg)) {
- __argValues[i].iVal = __intVal(arg);
- } else {
- __argValues[i].iVal = __unsignedLongIntVal(arg);
- if (__argValues[i].iVal == 0) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- }
- argValuePtr = &(__argValues[i].iVal);
- } else if (typeSymbol == @symbol(uint8)) {
- thisType = __get_ffi_type_uint8();
- if (! __isSmallInteger(arg)) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- __argValues[i].iVal = __intVal(arg);
- if (((unsigned)(__argValues[i].iVal)) > 0xFF) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- argValuePtr = &(__argValues[i].iVal);
- } else if (typeSymbol == @symbol(sint8)) {
- thisType = __get_ffi_type_sint8();
- if (! __isSmallInteger(arg)) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- __argValues[i].iVal = __intVal(arg);
- if (((__argValues[i].iVal) < -0x80) || ((__argValues[i].iVal) > 0x7F)) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- argValuePtr = &(__argValues[i].iVal);
- } else if (typeSymbol == @symbol(uint16)) {
- thisType = __get_ffi_type_uint16();
- if (! __isSmallInteger(arg)) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- __argValues[i].iVal = __intVal(arg);
- if (((unsigned)(__argValues[i].iVal)) > 0xFFFF) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- argValuePtr = &(__argValues[i].iVal);
- } else if (typeSymbol == @symbol(sint16)) {
- thisType = __get_ffi_type_sint16();
- if (! __isSmallInteger(arg)) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- __argValues[i].iVal = __intVal(arg);
- if (((__argValues[i].iVal) < -0x8000) || ((__argValues[i].iVal) > 0x7FFF)) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- argValuePtr = &(__argValues[i].iVal);
- } else if (typeSymbol == @symbol(float)) {
- thisType = __get_ffi_type_float();
- if (__isSmallInteger(arg)) {
- __argValues[i].fVal = (float)(__intVal(arg));
- } else if (__isFloat(arg)) {
- __argValues[i].fVal = (float)(__floatVal(arg));
- } else if (__isShortFloat(arg)) {
- __argValues[i].fVal = (float)(__shortFloatVal(arg));
- } else {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- argValuePtr = &(__argValues[i].fVal);
- } else if (typeSymbol == @symbol(double)) {
- thisType = __get_ffi_type_double();
- if (__isSmallInteger(arg)) {
- __argValues[i].dVal = (double)(__intVal(arg));
- } else if (__isFloat(arg)) {
- __argValues[i].dVal = (double)(__floatVal(arg));
- } else if (__isShortFloat(arg)) {
- __argValues[i].dVal = (double)(__shortFloatVal(arg));
- } else {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- argValuePtr = &(__argValues[i].dVal);
- } else if (typeSymbol == @symbol(void)) {
- thisType = __get_ffi_type_void();
- argValuePtr = &null;
- } else if (typeSymbol == @symbol(pointer)) {
- thisType = __get_ffi_type_pointer();
- if (__isExternalAddressLike(arg)) {
- __argValues[i].pointerVal = (void *)(__externalAddressVal(arg));
- } else if (__isExternalBytesLike(arg)) {
- __argValues[i].pointerVal = (void *)(__externalBytesVal(arg));
- } else if (__isByteArray(arg)) {
- __argValues[i].pointerVal = (void *)(__byteArrayVal(arg));
- } else if (__isFloatArray(arg)) {
- __argValues[i].pointerVal = (void *)(__FloatArrayInstPtr(arg)->f_element);
- } else if (__isDoubleArray(arg)) {
- __argValues[i].pointerVal = (void *)(__DoubleArrayInstPtr(arg)->d_element);
- } else if (__isString(arg) || __isSymbol(arg)) {
- __argValues[i].pointerVal = (void *)(__stringVal(arg));
- } else {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- argValuePtr = &(__argValues[i].pointerVal);;
- } else if (typeSymbol == @symbol(boolean)) {
- thisType = __get_ffi_type_uint();
-
- if (arg == true) {
- __argValues[i].iVal = 1;
- } else if (arg == false) {
- __argValues[i].iVal = 0;
- } else if (__isSmallInteger(arg)) {
- __argValues[i].iVal = __intVal(arg);
- } else {
- __argValues[i].iVal = __unsignedLongIntVal(arg);
- if (__argValues[i].iVal == 0) {
- failureCode = @symbol(InvalidArgument);
- goto error;
- }
- }
- argValuePtr = &(__argValues[i].iVal);
- } else {
- failureCode = @symbol(UnknownArgumentType);
- goto error;
- }
-
- __argTypes[i] = thisType;
- __argValuePointers[i] = argValuePtr;
- }
-
- __callType = FFI_DEFAULT_ABI;
-
-#ifdef CALLTYPE_FFI_STDCALL
- if ((__INST(callType) == @symbol(callTypeAPI))
- || (__INST(callType) == @symbol(WINAPI))
- || (__INST(callType) == @symbol(STDCALL))) {
- __callType = CALLTYPE_FFI_STDCALL;
- }
-#endif
-#ifdef CALLTYPE_FFI_V8
- if ((__INST(callType) == @symbol(callTypeV8))
- || (__INST(callType) == @symbol(V8))) {
- __callType = CALLTYPE_FFI_V8;
- }
-#endif
-#ifdef CALLTYPE_FFI_V9
- if ((__INST(callType) == @symbol(callTypeV9))
- || (__INST(callType) == @symbol(V9))) {
- __callType = CALLTYPE_FFI_V9;
- }
-#endif
-#ifdef CALLTYPE_FFI_UNIX64
- if ((__INST(callType) == @symbol(callTypeUnix64))
- || (__INST(callType) == @symbol(UNIX64))) {
- __callType = CALLTYPE_FFI_UNIX64;
- }
-#endif
-
- if (ffi_prep_cif(&__cif, __callType, __numArgs, __returnType, __argTypes) != FFI_OK) {
- failureCode = @symbol(FFIPrepareFailed);
- goto error;
- }
- ffi_call(&__cif, (VOIDFUNC)__INST(code_), __returnValuePointer, __argValuePointers);
-
- if ((returnTypeSymbol == @symbol(int))
- || (returnTypeSymbol == @symbol(int8))
- || (returnTypeSymbol == @symbol(int16))) {
- RETURN ( __MKINT(__returnValue.iVal) );
- }
- if ((returnTypeSymbol == @symbol(uint))
- || (returnTypeSymbol == @symbol(uint8))
- || (returnTypeSymbol == @symbol(uint16))) {
- RETURN ( __MKUINT(__returnValue.iVal) );
- }
- if (returnTypeSymbol == @symbol(boolean)) {
- RETURN ( __returnValue.iVal ? true : false );
- }
- if (returnTypeSymbol == @symbol(float)) {
- RETURN ( __MKFLOAT(__returnValue.fVal ));
- }
- if (returnTypeSymbol == @symbol(double)) {
- RETURN ( __MKFLOAT(__returnValue.dVal ));
- }
- if (returnTypeSymbol == @symbol(void)) {
- RETURN ( nil );
- }
- if (returnTypeSymbol == @symbol(pointer)) {
-printf("returnvalue: %x\n", __returnValue.pointerVal);
- RETURN ( __MKEXTERNALADDRESS(__returnValue.pointerVal) );
- }
- failureCode = @symbol(UnknownReturnType2);
-error: ;
-
-#else /* no FFI support */
- failureCode = @symbol(FFINotSupported);
-#endif /* HAVE_FFI */
-%}.
- failureCode notNil ifTrue:[
- self primitiveFailed
- ].
-!
-
linkToModule
"link this function to the external module.
I.e. retrieve the module handle and the code pointer."
@@ -989,8 +280,431 @@
argumentTypes := argTypes.
! !
+!ExternalLibraryFunction methodsFor:'private-invoking'!
+
+invokeFFIWithArguments:arguments
+ ^ self invokeFFIwithArguments:arguments virtualCallFor:nil
+!
+
+invokeFFIwithArguments:arguments virtualCallFor:aCPlusPlusObjectOrNil
+ |argTypeSymbols returnTypeSymbol failureCode returnValue stClass vtOffset|
+
+ argumentTypes notNil ifTrue:[
+ argTypeSymbols := argumentTypes collect:[:argType | self ffiTypeSymbolForType:argType].
+ ].
+ returnTypeSymbol := self ffiTypeSymbolForType:returnType.
+ aCPlusPlusObjectOrNil notNil ifTrue:[
+ "/ it must be a kind of ExternalStructure !!
+ (aCPlusPlusObjectOrNil isKindOf:ExternalStructure) ifFalse:[
+ self primitiveFailed.
+ ].
+ vtOffset := name.
+ (vtOffset between:0 and:10000) ifFalse:[
+ self primitiveFailed.
+ ].
+ ].
+
+%{ /* UNLIMITEDSTACK */
+#ifdef HAVE_FFI
+ ffi_cif __cif;
+ ffi_type *__argTypesIncludingThis[MAX_ARGS+1];
+ ffi_type **__argTypes = __argTypesIncludingThis;
+ ffi_type *__returnType = NULL;
+ union u {
+ int iVal;
+ float fVal;
+ double dVal;
+ void *pointerVal;
+ };
+ union u __argValuesIncludingThis[MAX_ARGS+1];
+ union u *__argValues = __argValuesIncludingThis;
+ union u __returnValue;
+ void *__argValuePointersIncludingThis[MAX_ARGS+1];
+ void **__argValuePointers = __argValuePointersIncludingThis;
+ void *__returnValuePointer;
+ int __numArgs, __numArgsIncludingThis;
+ static int null = 0;
+ int i;
+ ffi_abi __callType = FFI_DEFAULT_ABI;
+ VOIDFUNC codeAddress = (VOIDFUNC)__INST(code_);
+
+ if (arguments == nil) {
+ __numArgs = 0;
+ if (argTypeSymbols != nil) {
+ if (! __isArray(argTypeSymbols)
+ || (__arraySize(argTypeSymbols) != __numArgs)) {
+ failureCode = @symbol(ArgumentCountMismatch);
+ goto getOutOfHere;
+ }
+ }
+ } else {
+ if (! __isArray(arguments)
+ || ! __isArray(argTypeSymbols)
+ || (__arraySize(argTypeSymbols) != (__numArgs = __arraySize(arguments)))) {
+ failureCode = @symbol(ArgumentCountMismatch);
+ goto getOutOfHere;
+ }
+ }
+ if (__numArgs > MAX_ARGS) {
+ failureCode = @symbol(TooManyArguments);
+ goto getOutOfHere;
+ }
+
+ /*
+ * validate the return type
+ */
+ __returnValuePointer = &__returnValue;
+ if (returnTypeSymbol == @symbol(int)) {
+ __returnType = __get_ffi_type_sint();
+ } else if (returnTypeSymbol == @symbol(uint)) {
+ __returnType = __get_ffi_type_uint();
+ } else if (returnTypeSymbol == @symbol(long)) {
+ if (sizeof(long) == 4) {
+ __returnType = __get_ffi_type_sint32();
+ } else if (sizeof(long) == 8) {
+ __returnType = __get_ffi_type_sint64();
+ } else {
+ failureCode = @symbol(UnknownReturnType);
+ goto getOutOfHere;
+ }
+ } else if (returnTypeSymbol == @symbol(ulong)) {
+ if (sizeof(long) == 4) {
+ __returnType = __get_ffi_type_uint32();
+ }else if (sizeof(long) == 8) {
+ __returnType = __get_ffi_type_uint64();
+ } else {
+ failureCode = @symbol(UnknownReturnType);
+ goto getOutOfHere;
+ }
+ } else if (returnTypeSymbol == @symbol(boolean)) {
+ __returnType = __get_ffi_type_uint();
+ } else if (returnTypeSymbol == @symbol(uint8)) {
+ __returnType = __get_ffi_type_uint8();
+ } else if (returnTypeSymbol == @symbol(sint8)) {
+ __returnType = __get_ffi_type_sint8();
+ } else if (returnTypeSymbol == @symbol(uint16)) {
+ __returnType = __get_ffi_type_uint16();
+ } else if (returnTypeSymbol == @symbol(sint16)) {
+ __returnType = __get_ffi_type_sint16();
+ } else if (returnTypeSymbol == @symbol(float)) {
+ __returnType = __get_ffi_type_float();
+ } else if (returnTypeSymbol == @symbol(double)) {
+ __returnType = __get_ffi_type_double();
+ } else if (returnTypeSymbol == @symbol(void)) {
+ __returnType = __get_ffi_type_void();
+ __returnValuePointer = NULL;
+ } else if (returnTypeSymbol == @symbol(pointer)) {
+ __returnType = __get_ffi_type_pointer();
+ } else {
+ failureCode = @symbol(UnknownReturnType);
+ goto getOutOfHere;
+ }
+
+ /*
+ * validate the c++ object
+ */
+ if (aCPlusPlusObjectOrNil != nil) {
+ struct cPlusPlusInstance {
+ void **vTable;
+ };
+ struct cPlusPlusInstance *inst;
+
+ if (__isExternalAddressLike(aCPlusPlusObjectOrNil)) {
+ inst = (void *)(__externalAddressVal(aCPlusPlusObjectOrNil));
+ } else if (__isExternalBytesLike(aCPlusPlusObjectOrNil)) {
+ inst = (void *)(__externalBytesVal(aCPlusPlusObjectOrNil));
+ } else {
+ failureCode = @symbol(InvalidInstance);
+ goto getOutOfHere;
+ }
+ __argValues[0].pointerVal = inst;
+ __argValuePointersIncludingThis[0] = &(__argValues[0]);
+ __argTypes[0] = __get_ffi_type_pointer();
+
+ codeAddress = inst->vTable[__intVal(vtOffset)];
+
+ __argValuePointers = &__argValuePointersIncludingThis[1];
+ __argTypes = &__argTypesIncludingThis[1];
+ __argValues = &__argValuesIncludingThis[1];
+ __numArgsIncludingThis = __numArgs + 1;
+ } else {
+ __numArgsIncludingThis = __numArgs;
+ }
+
+ /*
+ * validate all arg types and setup arg-buffers
+ */
+ for (i=0; i<__numArgs; i++) {
+ ffi_type *thisType;
+ void *argValuePtr;
+ OBJ typeSymbol;
+ OBJ arg;
+
+ typeSymbol = __ArrayInstPtr(argTypeSymbols)->a_element[i];
+ arg = __ArrayInstPtr(arguments)->a_element[i];
+
+ if (typeSymbol == @symbol(long)) {
+ if (sizeof(long) == sizeof(int)) {
+ typeSymbol = @symbol(sint);
+ } else {
+ if (sizeof(long) == 4) {
+ typeSymbol = @symbol(sint32);
+ } else if (sizeof(long) == 8) {
+ typeSymbol = @symbol(sint64);
+ }
+ }
+ }
+ if (typeSymbol == @symbol(ulong)) {
+ if (sizeof(unsigned long) == sizeof(unsigned int)) {
+ typeSymbol = @symbol(uint);
+ } else {
+ if (sizeof(long) == 4) {
+ typeSymbol = @symbol(uint32);
+ } else if (sizeof(long) == 8) {
+ typeSymbol = @symbol(uint64);
+ }
+ }
+ }
+
+ if (typeSymbol == @symbol(int)) {
+ thisType = __get_ffi_type_sint();
+ if (__isSmallInteger(arg)) {
+ __argValues[i].iVal = __intVal(arg);
+ } else {
+ __argValues[i].iVal = __signedLongIntVal(arg);
+ if (__argValues[i].iVal == 0) {
+ failureCode = @symbol(InvalidArgument);
+ goto getOutOfHere;
+ }
+ }
+ argValuePtr = &(__argValues[i].iVal);
+ } else if (typeSymbol == @symbol(uint)) {
+ thisType = __get_ffi_type_uint();
+
+ if (__isSmallInteger(arg)) {
+ __argValues[i].iVal = __intVal(arg);
+ } else {
+ __argValues[i].iVal = __unsignedLongIntVal(arg);
+ if (__argValues[i].iVal == 0) {
+ failureCode = @symbol(InvalidArgument);
+ goto getOutOfHere;
+ }
+ }
+ argValuePtr = &(__argValues[i].iVal);
+ } else if (typeSymbol == @symbol(uint8)) {
+ thisType = __get_ffi_type_uint8();
+ if (! __isSmallInteger(arg)) {
+ failureCode = @symbol(InvalidArgument);
+ goto getOutOfHere;
+ }
+ __argValues[i].iVal = __intVal(arg);
+ if (((unsigned)(__argValues[i].iVal)) > 0xFF) {
+ failureCode = @symbol(InvalidArgument);
+ goto getOutOfHere;
+ }
+ argValuePtr = &(__argValues[i].iVal);
+ } else if (typeSymbol == @symbol(sint8)) {
+ thisType = __get_ffi_type_sint8();
+ if (! __isSmallInteger(arg)) {
+ failureCode = @symbol(InvalidArgument);
+ goto getOutOfHere;
+ }
+ __argValues[i].iVal = __intVal(arg);
+ if (((__argValues[i].iVal) < -0x80) || ((__argValues[i].iVal) > 0x7F)) {
+ failureCode = @symbol(InvalidArgument);
+ goto getOutOfHere;
+ }
+ argValuePtr = &(__argValues[i].iVal);
+ } else if (typeSymbol == @symbol(uint16)) {
+ thisType = __get_ffi_type_uint16();
+ if (! __isSmallInteger(arg)) {
+ failureCode = @symbol(InvalidArgument);
+ goto getOutOfHere;
+ }
+ __argValues[i].iVal = __intVal(arg);
+ if (((unsigned)(__argValues[i].iVal)) > 0xFFFF) {
+ failureCode = @symbol(InvalidArgument);
+ goto getOutOfHere;
+ }
+ argValuePtr = &(__argValues[i].iVal);
+ } else if (typeSymbol == @symbol(sint16)) {
+ thisType = __get_ffi_type_sint16();
+ if (! __isSmallInteger(arg)) {
+ failureCode = @symbol(InvalidArgument);
+ goto getOutOfHere;
+ }
+ __argValues[i].iVal = __intVal(arg);
+ if (((__argValues[i].iVal) < -0x8000) || ((__argValues[i].iVal) > 0x7FFF)) {
+ failureCode = @symbol(InvalidArgument);
+ goto getOutOfHere;
+ }
+ argValuePtr = &(__argValues[i].iVal);
+ } else if (typeSymbol == @symbol(float)) {
+ thisType = __get_ffi_type_float();
+ if (__isSmallInteger(arg)) {
+ __argValues[i].fVal = (float)(__intVal(arg));
+ } else if (__isFloat(arg)) {
+ __argValues[i].fVal = (float)(__floatVal(arg));
+ } else if (__isShortFloat(arg)) {
+ __argValues[i].fVal = (float)(__shortFloatVal(arg));
+ } else {
+ failureCode = @symbol(InvalidArgument);
+ goto getOutOfHere;
+ }
+ argValuePtr = &(__argValues[i].fVal);
+ } else if (typeSymbol == @symbol(double)) {
+ thisType = __get_ffi_type_double();
+ if (__isSmallInteger(arg)) {
+ __argValues[i].dVal = (double)(__intVal(arg));
+ } else if (__isFloat(arg)) {
+ __argValues[i].dVal = (double)(__floatVal(arg));
+ } else if (__isShortFloat(arg)) {
+ __argValues[i].dVal = (double)(__shortFloatVal(arg));
+ } else {
+ failureCode = @symbol(InvalidArgument);
+ goto getOutOfHere;
+ }
+ argValuePtr = &(__argValues[i].dVal);
+ } else if (typeSymbol == @symbol(void)) {
+ thisType = __get_ffi_type_void();
+ argValuePtr = &null;
+ } else if (typeSymbol == @symbol(pointer)) {
+ thisType = __get_ffi_type_pointer();
+ if (__isExternalAddressLike(arg)) {
+ __argValues[i].pointerVal = (void *)(__externalAddressVal(arg));
+ } else if (__isExternalBytesLike(arg)) {
+ __argValues[i].pointerVal = (void *)(__externalBytesVal(arg));
+ } else if (__isByteArray(arg)) {
+ __argValues[i].pointerVal = (void *)(__byteArrayVal(arg));
+ } else if (__isFloatArray(arg)) {
+ __argValues[i].pointerVal = (void *)(__FloatArrayInstPtr(arg)->f_element);
+ } else if (__isDoubleArray(arg)) {
+ __argValues[i].pointerVal = (void *)(__DoubleArrayInstPtr(arg)->d_element);
+ } else if (__isString(arg) || __isSymbol(arg)) {
+ __argValues[i].pointerVal = (void *)(__stringVal(arg));
+ } else {
+ failureCode = @symbol(InvalidArgument);
+ goto getOutOfHere;
+ }
+ argValuePtr = &(__argValues[i].pointerVal);;
+ } else if (typeSymbol == @symbol(boolean)) {
+ thisType = __get_ffi_type_uint();
+
+ if (arg == true) {
+ __argValues[i].iVal = 1;
+ } else if (arg == false) {
+ __argValues[i].iVal = 0;
+ } else if (__isSmallInteger(arg)) {
+ __argValues[i].iVal = __intVal(arg);
+ } else {
+ __argValues[i].iVal = __unsignedLongIntVal(arg);
+ if (__argValues[i].iVal == 0) {
+ failureCode = @symbol(InvalidArgument);
+ goto getOutOfHere;
+ }
+ }
+ argValuePtr = &(__argValues[i].iVal);
+ } else {
+ failureCode = @symbol(UnknownArgumentType);
+ goto getOutOfHere;
+ }
+
+ __argTypes[i] = thisType;
+ __argValuePointers[i] = argValuePtr;
+ }
+
+ __callType = FFI_DEFAULT_ABI;
+
+#ifdef CALLTYPE_FFI_STDCALL
+ if ((__INST(callType) == @symbol(callTypeAPI))
+ || (__INST(callType) == @symbol(WINAPI))
+ || (__INST(callType) == @symbol(STDCALL))) {
+ __callType = CALLTYPE_FFI_STDCALL;
+ }
+#endif
+#ifdef CALLTYPE_FFI_V8
+ if ((__INST(callType) == @symbol(callTypeV8))
+ || (__INST(callType) == @symbol(V8))) {
+ __callType = CALLTYPE_FFI_V8;
+ }
+#endif
+#ifdef CALLTYPE_FFI_V9
+ if ((__INST(callType) == @symbol(callTypeV9))
+ || (__INST(callType) == @symbol(V9))) {
+ __callType = CALLTYPE_FFI_V9;
+ }
+#endif
+#ifdef CALLTYPE_FFI_UNIX64
+ if ((__INST(callType) == @symbol(callTypeUnix64))
+ || (__INST(callType) == @symbol(UNIX64))) {
+ __callType = CALLTYPE_FFI_UNIX64;
+ }
+#endif
+
+ if (ffi_prep_cif(&__cif, __callType, __numArgsIncludingThis, __returnType, __argTypesIncludingThis) != FFI_OK) {
+ failureCode = @symbol(FFIPrepareFailed);
+ goto getOutOfHere;
+ }
+ ffi_call(&__cif, codeAddress, __returnValuePointer, __argValuePointersIncludingThis);
+
+ if ((returnTypeSymbol == @symbol(int))
+ || (returnTypeSymbol == @symbol(int8))
+ || (returnTypeSymbol == @symbol(int16))
+ || (returnTypeSymbol == @symbol(int32))) {
+ RETURN ( __MKINT(__returnValue.iVal) );
+ }
+ if ((returnTypeSymbol == @symbol(uint))
+ || (returnTypeSymbol == @symbol(uint8))
+ || (returnTypeSymbol == @symbol(uint16))
+ || (returnTypeSymbol == @symbol(uint32))) {
+ RETURN ( __MKUINT(__returnValue.iVal) );
+ }
+ if (returnTypeSymbol == @symbol(boolean)) {
+ RETURN ( __returnValue.iVal ? true : false );
+ }
+ if (returnTypeSymbol == @symbol(float)) {
+ RETURN ( __MKFLOAT(__returnValue.fVal ));
+ }
+ if (returnTypeSymbol == @symbol(double)) {
+ RETURN ( __MKFLOAT(__returnValue.dVal ));
+ }
+ if (returnTypeSymbol == @symbol(void)) {
+ RETURN ( nil );
+ }
+ if (returnTypeSymbol == @symbol(pointer)) {
+ returnValue = __MKEXTERNALADDRESS(__returnValue.pointerVal);
+ } else {
+ failureCode = @symbol(UnknownReturnType2);
+ }
+getOutOfHere: ;
+
+#else /* no FFI support */
+ failureCode = @symbol(FFINotSupported);
+#endif /* HAVE_FFI */
+%}.
+ failureCode notNil ifTrue:[
+ self primitiveFailed.
+ ^ nil
+ ].
+
+ returnType isCPointer ifTrue:[
+ returnType baseType isCStruct ifTrue:[
+ stClass := Smalltalk classNamed:returnType baseType name.
+ (stClass notNil and:[stClass isSubclassOf:ExternalStructure]) ifTrue:[
+ returnValue changeClassTo:stClass.
+ ].
+ ]
+ ].
+
+ ^ returnValue
+!
+
+invokeVirtualFFIOn:instance withArguments:arguments
+ ^ self invokeFFIwithArguments:arguments virtualCallFor:instance
+! !
+
!ExternalLibraryFunction class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/ExternalLibraryFunction.st,v 1.17 2006-05-02 22:13:59 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/ExternalLibraryFunction.st,v 1.18 2006-05-05 09:40:18 cg Exp $'
! !