ExternalLibraryFunction.st
changeset 9524 2af286bbcac3
parent 9519 ad18bf96758d
child 9525 120234adc94e
equal deleted inserted replaced
9523:84319324e99f 9524:2af286bbcac3
   514     "Modified: / 01-08-2006 / 13:55:35 / cg"
   514     "Modified: / 01-08-2006 / 13:55:35 / cg"
   515 !
   515 !
   516 
   516 
   517 invokeFFIwithArguments:arguments forCPPInstance:aCPlusPlusObjectOrNil 
   517 invokeFFIwithArguments:arguments forCPPInstance:aCPlusPlusObjectOrNil 
   518     |argTypeSymbols returnTypeSymbol failureCode failureInfo returnValue stClass vtOffset 
   518     |argTypeSymbols returnTypeSymbol failureCode failureInfo returnValue stClass vtOffset 
   519      virtual async unlimitedStack callTypeNumber|
   519      virtual async unlimitedStack callTypeNumber returnValueClass argValueClass|
   520 
   520 
   521     argumentTypes notNil ifTrue:[
   521     argumentTypes notNil ifTrue:[
   522         argTypeSymbols := argumentTypes collect:[:argType | self ffiTypeSymbolForType:argType].
   522         argTypeSymbols := argumentTypes collect:[:argType | self ffiTypeSymbolForType:argType].
   523     ].
   523     ].
   524     returnTypeSymbol := self ffiTypeSymbolForType:returnType.
   524     returnTypeSymbol := self ffiTypeSymbolForType:returnType.
   525 
   525 
   526     virtual := self isVirtualCPP.    
   526     virtual := self isVirtualCPP.    
   527     (virtual or:[self isNonVirtualCPP]) ifTrue:[
   527     (virtual "or:[self isNonVirtualCPP]") ifTrue:[
   528         aCPlusPlusObjectOrNil isNil ifTrue:[
   528         aCPlusPlusObjectOrNil isNil ifTrue:[
   529             "/ must have a c++ object instance
   529             "/ must have a c++ object instance
   530             self primitiveFailed.
   530             self primitiveFailed.
   531         ].
   531         ].
   532 
   532 
   669     } else if (returnTypeSymbol == @symbol(charPointer)) {
   669     } else if (returnTypeSymbol == @symbol(charPointer)) {
   670         __returnType = __get_ffi_type_pointer();
   670         __returnType = __get_ffi_type_pointer();
   671     } else if (returnTypeSymbol == @symbol(wcharPointer)) {
   671     } else if (returnTypeSymbol == @symbol(wcharPointer)) {
   672         __returnType = __get_ffi_type_pointer();
   672         __returnType = __get_ffi_type_pointer();
   673     } else {
   673     } else {
   674         failureCode = @symbol(UnknownReturnType);
   674         if (__isSymbol(returnTypeSymbol)
   675         goto getOutOfHere;
   675          && ((returnValueClass = __GLOBAL_GET(returnTypeSymbol)) != nil)) {
       
   676             if (! __isBehaviorLike(returnValueClass)) {
       
   677                 failureCode = @symbol(NonBehaviorReturnType);
       
   678                 goto getOutOfHere;
       
   679             }
       
   680             if (! __qIsSubclassOfExternalAddress(returnValueClass)) {
       
   681                 failureCode = @symbol(NonExternalAddressReturnType);
       
   682                 goto getOutOfHere;
       
   683             }
       
   684             __returnType = __get_ffi_type_pointer();
       
   685             returnTypeSymbol = @symbol(pointer);
       
   686         } else {
       
   687             failureCode = @symbol(UnknownReturnType);
       
   688             goto getOutOfHere;
       
   689         }
   676     }
   690     }
   677 
   691 
   678     /*
   692     /*
   679      * validate the c++ object
   693      * validate the c++ object
   680      */
   694      */
   711             printf("virtual codeAddress: %x\n", codeAddress);
   725             printf("virtual codeAddress: %x\n", codeAddress);
   712 #endif
   726 #endif
   713         }
   727         }
   714     } else {
   728     } else {
   715         __numArgsIncludingThis = __numArgs;
   729         __numArgsIncludingThis = __numArgs;
       
   730 #ifdef VERBOSE
       
   731         printf("codeAddress: %x\n", codeAddress);
       
   732 #endif
   716     }
   733     }
   717 
   734 
   718     /*
   735     /*
   719      * validate all arg types and setup arg-buffers
   736      * validate all arg types and setup arg-buffers
   720      */
   737      */
   901                 }
   918                 }
   902             }
   919             }
   903             argValuePtr = &(__argValues[i].pointerVal);;
   920             argValuePtr = &(__argValues[i].pointerVal);;
   904 
   921 
   905         } else if (typeSymbol == @symbol(pointer)) {
   922         } else if (typeSymbol == @symbol(pointer)) {
       
   923 commonPointerTypeArg: ;
   906             thisType = __get_ffi_type_pointer();
   924             thisType = __get_ffi_type_pointer();
   907             if (arg == nil) {
   925             if (arg == nil) {
   908                 __argValues[i].pointerVal = NULL;
   926                 __argValues[i].pointerVal = NULL;
   909             } else if (__isExternalAddressLike(arg)) {
   927             } else if (__isExternalAddressLike(arg)) {
   910                 __argValues[i].pointerVal = (void *)(__externalAddressVal(arg));
   928                 __argValues[i].pointerVal = (void *)(__externalAddressVal(arg));
   911             } else if (__isExternalBytesLike(arg)) {
   929             } else if (__isExternalBytesLike(arg)) {
   912                 __argValues[i].pointerVal = (void *)(__externalBytesVal(arg));
   930                 __argValues[i].pointerVal = (void *)(__externalBytesVal(arg));
   913             } else if (__isByteArray(arg)) {
       
   914                 if (async == true) goto badArgForAsyncCall;
       
   915                 __argValues[i].pointerVal = (void *)(__byteArrayVal(arg));
       
   916             } else if (__isByteArray(arg)) {
   931             } else if (__isByteArray(arg)) {
   917                 if (async == true) goto badArgForAsyncCall;
   932                 if (async == true) goto badArgForAsyncCall;
   918                 __argValues[i].pointerVal = (void *)(__byteArrayVal(arg));
   933                 __argValues[i].pointerVal = (void *)(__byteArrayVal(arg));
   919             } else if (__isFloatArray(arg)) {
   934             } else if (__isFloatArray(arg)) {
   920                 if (async == true) goto badArgForAsyncCall;
   935                 if (async == true) goto badArgForAsyncCall;
   959                     goto getOutOfHere;
   974                     goto getOutOfHere;
   960                 }
   975                 }
   961             }
   976             }
   962             argValuePtr = &(__argValues[i].iVal);
   977             argValuePtr = &(__argValues[i].iVal);
   963         } else {
   978         } else {
   964             failureCode = @symbol(UnknownArgumentType);
   979             if (__isSymbol(typeSymbol)
   965             goto getOutOfHere;
   980              && ((argValueClass = __GLOBAL_GET(typeSymbol)) != nil)) {
       
   981                 if (! __isBehaviorLike(argValueClass)) {
       
   982                     failureCode = @symbol(NonBehaviorArgumentType);
       
   983                     goto getOutOfHere;
       
   984                 }
       
   985                 if (! __qIsSubclassOfExternalAddress(argValueClass)) {
       
   986                     failureCode = @symbol(NonExternalAddressArgumentType);
       
   987                     goto getOutOfHere;
       
   988                 }
       
   989                 goto commonPointerTypeArg; /* sorry */
       
   990             } else {
       
   991                 failureCode = @symbol(UnknownArgumentType);
       
   992                 goto getOutOfHere;
       
   993             }
   966         }
   994         }
   967 
   995 
   968         __argTypes[i] = thisType;
   996         __argTypes[i] = thisType;
   969         __argValuePointers[i] = argValuePtr;
   997         __argValuePointers[i] = argValuePtr;
   970 
   998 
       
   999 #ifdef VERBOSE
   971         printf("arg%d: %x\n", i, __argValues[i].iVal);
  1000         printf("arg%d: %x\n", i, __argValues[i].iVal);
       
  1001 #endif
   972     }
  1002     }
   973     failureInfo = nil;
  1003     failureInfo = nil;
   974 
  1004 
   975     __callType = FFI_DEFAULT_ABI;
  1005     __callType = FFI_DEFAULT_ABI;
   976 
  1006 
   998     if (ffi_prep_cif(&__cif, __callType, __numArgsIncludingThis, __returnType, __argTypesIncludingThis) != FFI_OK) {
  1028     if (ffi_prep_cif(&__cif, __callType, __numArgsIncludingThis, __returnType, __argTypesIncludingThis) != FFI_OK) {
   999         failureCode = @symbol(FFIPrepareFailed);
  1029         failureCode = @symbol(FFIPrepareFailed);
  1000         goto getOutOfHere;
  1030         goto getOutOfHere;
  1001     }
  1031     }
  1002     if (async == true) {
  1032     if (async == true) {
       
  1033 #ifdef VERBOSE
       
  1034         printf("async call 0x%x\n", codeAddress);
       
  1035 #endif
  1003 #ifdef WIN32
  1036 #ifdef WIN32
  1004         __STX_C_CALL4( "ffi_call", ffi_call, &__cif, codeAddress, __returnValuePointer, __argValuePointersIncludingThis);
  1037         __STX_C_CALL4( "ffi_call", ffi_call, &__cif, codeAddress, __returnValuePointer, __argValuePointersIncludingThis);
  1005 #else
  1038 #else
  1006         __BEGIN_INTERRUPTABLE__
  1039         __BEGIN_INTERRUPTABLE__
  1007         ffi_call(&__cif, codeAddress, __returnValuePointer, __argValuePointersIncludingThis);
  1040         ffi_call(&__cif, codeAddress, __returnValuePointer, __argValuePointersIncludingThis);
  1008         __END_INTERRUPTABLE__
  1041         __END_INTERRUPTABLE__
  1009 #endif
  1042 #endif
  1010     } else {
  1043     } else {
  1011         if (unlimitedStack == true) {
  1044         if (unlimitedStack == true) {
       
  1045 #ifdef VERBOSE
       
  1046             printf("UNLIMITEDSTACKCALL call 0x%x\n", codeAddress);
       
  1047 #endif
  1012 #if 0
  1048 #if 0
  1013             __UNLIMITEDSTACKCALL__(ffi_call, &__cif, codeAddress, __returnValuePointer, __argValuePointersIncludingThis);
  1049             __UNLIMITEDSTACKCALL__(ffi_call, &__cif, codeAddress, __returnValuePointer, __argValuePointersIncludingThis);
  1014 #endif
  1050 #endif
  1015         } else {
  1051         } else {
       
  1052 #ifdef VERBOSE
       
  1053             printf("call 0x%x\n", codeAddress);
       
  1054 #endif
  1016             ffi_call(&__cif, codeAddress, __returnValuePointer, __argValuePointersIncludingThis);
  1055             ffi_call(&__cif, codeAddress, __returnValuePointer, __argValuePointersIncludingThis);
  1017         }
  1056         }
  1018     }
  1057     }
  1019 printf("retval is %d (0x%x)\n", __returnValue.iVal, __returnValue.iVal);
  1058 #ifdef VERBOSE
       
  1059     printf("retval is %d (0x%x)\n", __returnValue.iVal, __returnValue.iVal);
       
  1060 #endif
  1020     if ((returnTypeSymbol == @symbol(sint))
  1061     if ((returnTypeSymbol == @symbol(sint))
  1021      || (returnTypeSymbol == @symbol(sint8))
  1062      || (returnTypeSymbol == @symbol(sint8))
  1022      || (returnTypeSymbol == @symbol(sint16))
  1063      || (returnTypeSymbol == @symbol(sint16))
  1023      || (returnTypeSymbol == @symbol(sint32))) {
  1064      || (returnTypeSymbol == @symbol(sint32))) {
  1024         RETURN ( __MKINT(__returnValue.iVal) );
  1065         RETURN ( __MKINT(__returnValue.iVal) );
  1068         self primitiveFailed.
  1109         self primitiveFailed.
  1069         ^ nil
  1110         ^ nil
  1070     ].
  1111     ].
  1071 
  1112 
  1072     returnType isSymbol ifTrue:[
  1113     returnType isSymbol ifTrue:[
       
  1114         returnValueClass notNil ifTrue:[
       
  1115             returnValue changeClassTo:returnValueClass
       
  1116         ].
  1073     ] ifFalse:[
  1117     ] ifFalse:[
  1074         returnType isCPointer ifTrue:[
  1118         returnType isCPointer ifTrue:[
  1075             returnType baseType isCStruct ifTrue:[
  1119             returnType baseType isCStruct ifTrue:[
  1076                 stClass := Smalltalk classNamed:returnType baseType name.
  1120                 stClass := Smalltalk classNamed:returnType baseType name.
  1077                 stClass notNil ifTrue:[
  1121                 stClass notNil ifTrue:[
  1091 ! !
  1135 ! !
  1092 
  1136 
  1093 !ExternalLibraryFunction class methodsFor:'documentation'!
  1137 !ExternalLibraryFunction class methodsFor:'documentation'!
  1094 
  1138 
  1095 version
  1139 version
  1096     ^ '$Header: /cvs/stx/stx/libbasic/ExternalLibraryFunction.st,v 1.40 2006-08-11 08:56:53 ca Exp $'
  1140     ^ '$Header: /cvs/stx/stx/libbasic/ExternalLibraryFunction.st,v 1.41 2006-08-11 10:27:28 ca Exp $'
  1097 ! !
  1141 ! !
  1098 
  1142 
  1099 ExternalLibraryFunction initialize!
  1143 ExternalLibraryFunction initialize!