--- a/ExternalLibraryFunction.st Wed Apr 10 05:58:34 2019 +0200
+++ b/ExternalLibraryFunction.st Wed Apr 10 06:08:33 2019 +0200
@@ -1435,13 +1435,16 @@
# define __HI32(ll) (((ll)>>32) & 0xFFFFFFFFL)
# endif
# endif
-
+# define MAX_NUM_STRUCT_ARGS 1
+# define MAX_NUM_STRUCT_FIELDS 4
ffi_cif __cif;
ffi_type *__argTypesIncludingThis[MAX_ARGS+1];
ffi_type **__argTypes = __argTypesIncludingThis;
ffi_type *__returnType = NULL;
ffi_type *thisType;
+ ffi_type structTypes[MAX_NUM_STRUCT_ARGS];
+ ffi_type *structTypeFields[MAX_NUM_STRUCT_ARGS][MAX_NUM_STRUCT_FIELDS+1];
ffi_abi __callType = FFI_DEFAULT_ABI;
#else
@@ -1455,6 +1458,7 @@
#endif
int __numFloatOrDoubleArgs = 0;
+ int numStructArgs = 0;
union u {
INT iVal;
@@ -2044,89 +2048,134 @@
} else if (__isStringLike(arg)) {
if (async == true) {
badArgForAsyncCall: ;
- DEBUGCODE_IF( @global(Verbose), {
- printf("invalidArgument: arg%d not allowed for async call [%d]\n", i+1, __LINE__);
- })
- __FAIL__(@symbol(BadArgForAsyncCall))
- }
- __argValues[i].pointerVal = (void *)(__stringVal(arg));
- } else if (__isBytes(arg) || __isWords(arg) || __isLongs(arg)) {
- char *p = (char *)(__byteArrayVal(arg));
- int nInstBytes;
- OBJ cls;
-
- if (async == true) goto badArgForAsyncCall;
- cls = __qClass(arg);
- nInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
- __argValues[i].pointerVal = p + nInstBytes;
- } else {
- DEBUGCODE_IF( @global(Verbose), {
- printf("invalidArgument: arg%d non pointer value [%d]\n", i+1, __LINE__);
- })
- __FAIL__(@symbol(InvalidArgument))
- }
- argValuePtr = &(__argValues[i].pointerVal);;
-
- } else if (typeSymbol == @symbol(bool)) {
- thisType = 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) {
- DEBUGCODE_IF( @global(Verbose), {
- printf("invalidArgument: arg%d non bool value [%d]\n", i+1, __LINE__);
- })
- __FAIL__(@symbol(InvalidArgument))
- }
- }
- argValuePtr = &(__argValues[i].iVal);
- } else {
- if (__isSymbol(typeSymbol)
- && ((argValueClass = __GLOBAL_GET(typeSymbol)) != nil)) {
- if (! __isBehaviorLike(argValueClass)) {
- __FAIL__(@symbol(NonBehaviorArgumentType))
- }
- if (! __qIsSubclassOfExternalAddress(argValueClass)) {
- __FAIL__(@symbol(NonExternalAddressArgumentType))
- }
- goto commonPointerTypeArg; /* sorry */
- } else {
- __FAIL__(@symbol(UnknownArgumentType))
- }
- }
-
- __argTypes[i] = thisType;
- __argValuePointers[i] = argValuePtr;
-
- if ((thisType == TYPE_FLOAT) || (thisType == TYPE_DOUBLE)) {
- __numFloatOrDoubleArgs++;
- }
- DEBUGCODE_IF( @global(Verbose), {
- char *typeString = "TYPE_OTHER";
-
- if (thisType == TYPE_POINTER) {
- typeString = "TYPE_POINTER";
- } else if (thisType == TYPE_VOID) {
- typeString = "TYPE_VOID";
- } else if (thisType == TYPE_FLOAT) {
- typeString = "TYPE_FLOAT";
- } else if (thisType == TYPE_DOUBLE) {
- typeString = "TYPE_DOUBLE";
- } else if (thisType == TYPE_UINT) {
- typeString = "TYPE_UINT";
- } else if (thisType == TYPE_SINT) {
- typeString = "TYPE_SINT";
- }
- printf("arg%d: %"_lx_" type:%"_lx_" (%s)\n",
- i+1,
- (INT)(__argValues[i].iVal), (INT)thisType, typeString);
- })
+ DEBUGCODE_IF( @global(Verbose), {
+ printf("invalidArgument: arg%d not allowed for async call [%d]\n", i+1, __LINE__);
+ })
+ __FAIL__(@symbol(BadArgForAsyncCall))
+ }
+ __argValues[i].pointerVal = (void *)(__stringVal(arg));
+ } else if (__isBytes(arg) || __isWords(arg) || __isLongs(arg)) {
+ char *p = (char *)(__byteArrayVal(arg));
+ int nInstBytes;
+ OBJ cls;
+
+ if (async == true) goto badArgForAsyncCall;
+ cls = __qClass(arg);
+ nInstBytes = __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+ __argValues[i].pointerVal = p + nInstBytes;
+ } else {
+ DEBUGCODE_IF( @global(Verbose), {
+ printf("invalidArgument: arg%d non pointer value [%d]\n", i+1, __LINE__);
+ })
+ __FAIL__(@symbol(InvalidArgument))
+ }
+ argValuePtr = &(__argValues[i].pointerVal);;
+
+ } else if (typeSymbol == @symbol(bool)) {
+ thisType = 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) {
+ DEBUGCODE_IF( @global(Verbose), {
+ printf("invalidArgument: arg%d non bool value [%d]\n", i+1, __LINE__);
+ })
+ __FAIL__(@symbol(InvalidArgument))
+ }
+ }
+ argValuePtr = &(__argValues[i].iVal);
+ } else {
+ if (__isSymbol(typeSymbol)
+ && ((argValueClass = __GLOBAL_GET(typeSymbol)) != nil)) {
+ if (! __isBehaviorLike(argValueClass)) {
+ __FAIL__(@symbol(NonBehaviorArgumentType))
+ }
+ if (! __qIsSubclassOfExternalAddress(argValueClass)) {
+ __FAIL__(@symbol(NonExternalAddressArgumentType))
+ }
+ goto commonPointerTypeArg; /* sorry */
+ } else {
+ if (__isArray(typeSymbol)) {
+ // struct
+ int numFields = __arraySize(typeSymbol);
+ int i;
+ ffi_type **fieldTypes;
+
+ if (numStructArgs >= MAX_NUM_STRUCT_ARGS) {
+ __FAIL__(@symbol(TooManyStructArguments))
+ }
+ if (numFields > MAX_NUM_STRUCT_FIELDS) {
+ __FAIL__(@symbol(TooManyStructFields))
+ }
+ fieldTypes = &(structTypeFields[numStructArgs][0]);
+
+ structTypes[numStructArgs].size = 0;
+ structTypes[numStructArgs].alignment = 0;
+ structTypes[numStructArgs].elements = fieldTypes;
+ for (i=0; i<numFields; i++) {
+ OBJ fieldTypeSymbol = __arrayVal(typeSymbol)[i];
+
+ if (fieldTypeSymbol == @symbol(float)) {
+ fieldTypes[i] = TYPE_FLOAT;
+ } else if (fieldTypeSymbol == @symbol(double)) {
+ fieldTypes[i] = TYPE_DOUBLE;
+ } else if (fieldTypeSymbol == @symbol(int)) {
+ fieldTypes[i] = TYPE_SINT;
+ } else {
+ __FAIL__(@symbol(UnsupportedFieldType))
+ }
+ }
+ fieldTypes[i] = NULL;
+ thisType = &(structTypes[numStructArgs]);
+ numStructArgs++;
+ // arg must be either a byteArray or externalBytes pointing to the struct
+ // i.e. a CDatum's underlying storage
+ if (__isByteArray(arg)) {
+ if (async == true) goto badArgForAsyncCall;
+ argValuePtr = (void *)(__byteArrayVal(arg));
+ } else if (__isExternalAddressLike(arg)) {
+ argValuePtr = (void *)(__externalAddressVal(arg));
+ } else if (__isExternalBytesLike(arg)) {
+ argValuePtr = (void *)(__externalBytesVal(arg));
+ } else {
+ __FAIL__(@symbol(InvalidArgument))
+ }
+ }
+ }
+ }
+
+ __argTypes[i] = thisType;
+ __argValuePointers[i] = argValuePtr;
+
+ if ((thisType == TYPE_FLOAT) || (thisType == TYPE_DOUBLE)) {
+ __numFloatOrDoubleArgs++;
+ }
+ DEBUGCODE_IF( @global(Verbose), {
+ char *typeString = "TYPE_OTHER";
+
+ if (thisType == TYPE_POINTER) {
+ typeString = "TYPE_POINTER";
+ } else if (thisType == TYPE_VOID) {
+ typeString = "TYPE_VOID";
+ } else if (thisType == TYPE_FLOAT) {
+ typeString = "TYPE_FLOAT";
+ } else if (thisType == TYPE_DOUBLE) {
+ typeString = "TYPE_DOUBLE";
+ } else if (thisType == TYPE_UINT) {
+ typeString = "TYPE_UINT";
+ } else if (thisType == TYPE_SINT) {
+ typeString = "TYPE_SINT";
+ }
+ printf("arg%d: %"_lx_" type:%"_lx_" (%s)\n",
+ i+1,
+ (INT)(__argValues[i].iVal), (INT)thisType, typeString);
+ })
}
failureInfo = nil;