*** empty log message ***
authorca
Fri, 11 Aug 2006 12:27:28 +0200
changeset 9524 2af286bbcac3
parent 9523 84319324e99f
child 9525 120234adc94e
*** empty log message ***
ExternalLibraryFunction.st
--- a/ExternalLibraryFunction.st	Fri Aug 11 11:06:50 2006 +0200
+++ b/ExternalLibraryFunction.st	Fri Aug 11 12:27:28 2006 +0200
@@ -516,7 +516,7 @@
 
 invokeFFIwithArguments:arguments forCPPInstance:aCPlusPlusObjectOrNil 
     |argTypeSymbols returnTypeSymbol failureCode failureInfo returnValue stClass vtOffset 
-     virtual async unlimitedStack callTypeNumber|
+     virtual async unlimitedStack callTypeNumber returnValueClass argValueClass|
 
     argumentTypes notNil ifTrue:[
         argTypeSymbols := argumentTypes collect:[:argType | self ffiTypeSymbolForType:argType].
@@ -524,7 +524,7 @@
     returnTypeSymbol := self ffiTypeSymbolForType:returnType.
 
     virtual := self isVirtualCPP.    
-    (virtual or:[self isNonVirtualCPP]) ifTrue:[
+    (virtual "or:[self isNonVirtualCPP]") ifTrue:[
         aCPlusPlusObjectOrNil isNil ifTrue:[
             "/ must have a c++ object instance
             self primitiveFailed.
@@ -671,8 +671,22 @@
     } else if (returnTypeSymbol == @symbol(wcharPointer)) {
         __returnType = __get_ffi_type_pointer();
     } else {
-        failureCode = @symbol(UnknownReturnType);
-        goto getOutOfHere;
+        if (__isSymbol(returnTypeSymbol)
+         && ((returnValueClass = __GLOBAL_GET(returnTypeSymbol)) != nil)) {
+            if (! __isBehaviorLike(returnValueClass)) {
+                failureCode = @symbol(NonBehaviorReturnType);
+                goto getOutOfHere;
+            }
+            if (! __qIsSubclassOfExternalAddress(returnValueClass)) {
+                failureCode = @symbol(NonExternalAddressReturnType);
+                goto getOutOfHere;
+            }
+            __returnType = __get_ffi_type_pointer();
+            returnTypeSymbol = @symbol(pointer);
+        } else {
+            failureCode = @symbol(UnknownReturnType);
+            goto getOutOfHere;
+        }
     }
 
     /*
@@ -713,6 +727,9 @@
         }
     } else {
         __numArgsIncludingThis = __numArgs;
+#ifdef VERBOSE
+        printf("codeAddress: %x\n", codeAddress);
+#endif
     }
 
     /*
@@ -903,6 +920,7 @@
             argValuePtr = &(__argValues[i].pointerVal);;
 
         } else if (typeSymbol == @symbol(pointer)) {
+commonPointerTypeArg: ;
             thisType = __get_ffi_type_pointer();
             if (arg == nil) {
                 __argValues[i].pointerVal = NULL;
@@ -913,9 +931,6 @@
             } else if (__isByteArray(arg)) {
                 if (async == true) goto badArgForAsyncCall;
                 __argValues[i].pointerVal = (void *)(__byteArrayVal(arg));
-            } else if (__isByteArray(arg)) {
-                if (async == true) goto badArgForAsyncCall;
-                __argValues[i].pointerVal = (void *)(__byteArrayVal(arg));
             } else if (__isFloatArray(arg)) {
                 if (async == true) goto badArgForAsyncCall;
                 __argValues[i].pointerVal = (void *)(__FloatArrayInstPtr(arg)->f_element);
@@ -961,14 +976,29 @@
             }
             argValuePtr = &(__argValues[i].iVal);
         } else {
-            failureCode = @symbol(UnknownArgumentType);
-            goto getOutOfHere;
+            if (__isSymbol(typeSymbol)
+             && ((argValueClass = __GLOBAL_GET(typeSymbol)) != nil)) {
+                if (! __isBehaviorLike(argValueClass)) {
+                    failureCode = @symbol(NonBehaviorArgumentType);
+                    goto getOutOfHere;
+                }
+                if (! __qIsSubclassOfExternalAddress(argValueClass)) {
+                    failureCode = @symbol(NonExternalAddressArgumentType);
+                    goto getOutOfHere;
+                }
+                goto commonPointerTypeArg; /* sorry */
+            } else {
+                failureCode = @symbol(UnknownArgumentType);
+                goto getOutOfHere;
+            }
         }
 
         __argTypes[i] = thisType;
         __argValuePointers[i] = argValuePtr;
 
+#ifdef VERBOSE
         printf("arg%d: %x\n", i, __argValues[i].iVal);
+#endif
     }
     failureInfo = nil;
 
@@ -1000,6 +1030,9 @@
         goto getOutOfHere;
     }
     if (async == true) {
+#ifdef VERBOSE
+        printf("async call 0x%x\n", codeAddress);
+#endif
 #ifdef WIN32
         __STX_C_CALL4( "ffi_call", ffi_call, &__cif, codeAddress, __returnValuePointer, __argValuePointersIncludingThis);
 #else
@@ -1009,14 +1042,22 @@
 #endif
     } else {
         if (unlimitedStack == true) {
+#ifdef VERBOSE
+            printf("UNLIMITEDSTACKCALL call 0x%x\n", codeAddress);
+#endif
 #if 0
             __UNLIMITEDSTACKCALL__(ffi_call, &__cif, codeAddress, __returnValuePointer, __argValuePointersIncludingThis);
 #endif
         } else {
+#ifdef VERBOSE
+            printf("call 0x%x\n", codeAddress);
+#endif
             ffi_call(&__cif, codeAddress, __returnValuePointer, __argValuePointersIncludingThis);
         }
     }
-printf("retval is %d (0x%x)\n", __returnValue.iVal, __returnValue.iVal);
+#ifdef VERBOSE
+    printf("retval is %d (0x%x)\n", __returnValue.iVal, __returnValue.iVal);
+#endif
     if ((returnTypeSymbol == @symbol(sint))
      || (returnTypeSymbol == @symbol(sint8))
      || (returnTypeSymbol == @symbol(sint16))
@@ -1070,6 +1111,9 @@
     ].
 
     returnType isSymbol ifTrue:[
+        returnValueClass notNil ifTrue:[
+            returnValue changeClassTo:returnValueClass
+        ].
     ] ifFalse:[
         returnType isCPointer ifTrue:[
             returnType baseType isCStruct ifTrue:[
@@ -1093,7 +1137,7 @@
 !ExternalLibraryFunction class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/ExternalLibraryFunction.st,v 1.40 2006-08-11 08:56:53 ca Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/ExternalLibraryFunction.st,v 1.41 2006-08-11 10:27:28 ca Exp $'
 ! !
 
 ExternalLibraryFunction initialize!