ExternalLibraryFunction.st
changeset 9321 734c7c432461
parent 8891 c30a030ff5ec
child 9322 41c391bfbf03
equal deleted inserted replaced
9320:3915cefea352 9321:734c7c432461
    42     ^ self new
    42     ^ self new
    43         name:functionName module:moduleName callType:callType 
    43         name:functionName module:moduleName callType:callType 
    44         returnType:returnType argumentTypes:argTypes
    44         returnType:returnType argumentTypes:argTypes
    45 ! !
    45 ! !
    46 
    46 
       
    47 !ExternalLibraryFunction class methodsFor:'constants'!
       
    48 
       
    49 callTypeAPI
       
    50     ^ #callTypeAPI
       
    51 !
       
    52 
       
    53 callTypeC
       
    54     ^ #callTypeC
       
    55 !
       
    56 
       
    57 callTypeCDecl
       
    58     ^ #callTypeCDecl
       
    59 !
       
    60 
       
    61 callTypeOLE
       
    62     ^ #callTypeOLE
       
    63 ! !
       
    64 
       
    65 !ExternalLibraryFunction methodsFor:'accessing'!
       
    66 
       
    67 argumentTypes
       
    68     ^ argumentTypes
       
    69 ! !
       
    70 
    47 !ExternalLibraryFunction methodsFor:'invoking'!
    71 !ExternalLibraryFunction methodsFor:'invoking'!
    48 
    72 
    49 invoke
    73 invoke
    50 
    74     self hasCode ifFalse:[
    51     moduleHandle isNil ifTrue:[
    75         self prepareInvoke.
    52         self linkToModule.
    76     ].
    53         self setupFFI.
    77     ^ self invokeFFIWithArguments:#()
    54     ].
       
    55 
       
    56     ^ self invokeFFI
       
    57 !
    78 !
    58 
    79 
    59 invokeWith:arg
    80 invokeWith:arg
    60 
    81     self hasCode ifFalse:[
    61     moduleHandle isNil ifTrue:[
    82         self prepareInvoke.
    62         self linkToModule.
    83     ].
    63         self setupFFI.
    84     ^ self invokeFFIWithArguments:(Array with:arg)
    64     ].
    85 !
    65 
    86 
    66     ^ self invokeFFI
    87 invokeWith:arg1 with:arg2
    67 
    88     self hasCode ifFalse:[
    68     "
    89         self prepareInvoke.
    69         self new test:'abc'
    90     ].
    70     "
    91     ^ self invokeFFIWithArguments:(Array with:arg1 with:arg2)
       
    92 !
       
    93 
       
    94 invokeWith:arg1 with:arg2 with:arg3
       
    95     self hasCode ifFalse:[
       
    96         self prepareInvoke.
       
    97     ].
       
    98     ^ self invokeFFIWithArguments:(Array with:arg1 with:arg2 with:arg3)
       
    99 !
       
   100 
       
   101 invokeWith:arg1 with:arg2 with:arg3 with:arg4
       
   102     self hasCode ifFalse:[
       
   103         self prepareInvoke.
       
   104     ].
       
   105     ^ self invokeFFIWithArguments:(Array with:arg1 with:arg2 with:arg3 with:arg4)
       
   106 !
       
   107 
       
   108 invokeWithArguments:argArray
       
   109     self hasCode ifFalse:[
       
   110         self prepareInvoke.
       
   111     ].
       
   112     ^ self invokeFFIWithArguments:argArray
       
   113 ! !
       
   114 
       
   115 !ExternalLibraryFunction methodsFor:'printing'!
       
   116 
       
   117 printOn:aStream
       
   118     aStream nextPutAll:'<'.
       
   119     callType printOn:aStream.
       
   120     aStream nextPutAll:' '.
       
   121     name printOn:aStream.
       
   122     aStream nextPutAll:' module:'.
       
   123     moduleName printOn:aStream.
       
   124     aStream nextPutAll:'>'.
    71 ! !
   125 ! !
    72 
   126 
    73 !ExternalLibraryFunction methodsFor:'private'!
   127 !ExternalLibraryFunction methodsFor:'private'!
    74 
   128 
    75 invokeFFI
   129 invokeFFIWithArguments:arguments
    76     "invoke foreign function interface"
   130     |ffiArgTypes failureCode|
       
   131 
       
   132     argumentTypes notNil ifTrue:[
       
   133         ffiArgTypes := argumentTypes collect:[:argType | self ffiArgTypeForType:argType].
       
   134     ].
       
   135 %{
       
   136 #if defined(i386)
       
   137 # ifndef STX_FFI_TYPE_VOID
       
   138 #  define STX_FFI_TYPE_VOID         0
       
   139 #  define STX_FFI_TYPE_INT          1
       
   140 #  define STX_FFI_TYPE_FLOAT        2
       
   141 #  define STX_FFI_TYPE_DOUBLE       3
       
   142 #  define STX_FFI_TYPE_LONGDOUBLE   4
       
   143 #  define STX_FFI_TYPE_UINT8        5
       
   144 #  define STX_FFI_TYPE_SINT8        6
       
   145 #  define STX_FFI_TYPE_UINT16       7
       
   146 #  define STX_FFI_TYPE_SINT16       8
       
   147 #  define STX_FFI_TYPE_UINT32       9
       
   148 #  define STX_FFI_TYPE_SINT32       10
       
   149 #  define STX_FFI_TYPE_UINT64       11
       
   150 #  define STX_FFI_TYPE_SINT64       12
       
   151 #  define STX_FFI_TYPE_STRUCT       13
       
   152 #  define STX_FFI_TYPE_POINTER      14
       
   153 
       
   154 # define MAX_NUMARGS    128
       
   155 typedef void * ffi_type;
       
   156 # endif
       
   157 
       
   158     void *argValues[MAX_NUMARGS];
       
   159     ffi_type *argtypes[MAX_NUMARGS];
       
   160     int numArgs;
       
   161     int i;
       
   162 
       
   163     if (arguments == nil) {
       
   164         numArgs = 0;
       
   165         if (ffiArgTypes != nil) {
       
   166             if (! __isArray(ffiArgTypes)) goto error;
       
   167             if (__arraySize(ffiArgTypes) != numArgs) goto error;
       
   168         }
       
   169     } else {
       
   170         if (! __isArray(arguments)) goto error;
       
   171         numArgs = __arraySize(arguments);
       
   172         if (! __isArray(ffiArgTypes)) goto error;
       
   173         if (__arraySize(ffiArgTypes) != numArgs) goto error;
       
   174     }
       
   175     if (numArgs > MAX_NUMARGS) {
       
   176         failureCode = @symbol(TooManyArguments);
       
   177         goto error;
       
   178     }
       
   179     for (i=0; i<numArgs; i++) {
       
   180         switch (__intVal( __ArrayInstPtr(ffiArgTypes)->a_element[i]) ) {
       
   181             case STX_FFI_TYPE_VOID:
       
   182             case STX_FFI_TYPE_INT:
       
   183             case STX_FFI_TYPE_FLOAT:
       
   184             case STX_FFI_TYPE_DOUBLE:
       
   185             case STX_FFI_TYPE_LONGDOUBLE:
       
   186             case STX_FFI_TYPE_UINT8:
       
   187             case STX_FFI_TYPE_SINT8:
       
   188             case STX_FFI_TYPE_UINT16:
       
   189             case STX_FFI_TYPE_SINT16:
       
   190             case STX_FFI_TYPE_UINT32:
       
   191             case STX_FFI_TYPE_SINT32:
       
   192             case STX_FFI_TYPE_UINT64:
       
   193             case STX_FFI_TYPE_SINT64:
       
   194             case STX_FFI_TYPE_STRUCT:
       
   195             case STX_FFI_TYPE_POINTER:
       
   196             default:
       
   197                 failureCode = @symbol(UnknownArgumentType);
       
   198                 goto error;
       
   199         }
       
   200     }
       
   201 
       
   202 #else
       
   203     argtypes = (ffi_type **)C_alloca(sizeof(ffi_type *) * (n + 3));
       
   204     argvalues = (void **)C_alloca(sizeof(void *) * (n + 3));
       
   205     argtypes[ 0 ] = &ffi_type_pointer;
       
   206     argtypes[ 1 ] = &ffi_type_pointer;
       
   207     argtypes[ 2 ] = &ffi_type_pointer;
       
   208     c = n + 2;
       
   209     argvalues[ 0 ] = &c;
       
   210     argvalues[ 1 ] = &fn;
       
   211     argvalues[ 2 ] = &k;
       
   212 
       
   213     for(i = 0; i < n; ++i) {
       
   214       argtypes[ i + 3 ] = &ffi_type_pointer;
       
   215       argvalues[ i + 3 ] = C_temporary_stack_bottom - (i + 1);
       
   216     }
       
   217 
       
   218     C_temporary_stack = C_temporary_stack_bottom;
       
   219     status = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, n + 3, &ffi_type_void, argtypes);
       
   220     assert(status == FFI_OK);
       
   221     ffi_call(&cif, (void *)C_block_item(fn, 0), NULL, argvalues);
       
   222 #endif
       
   223 error: ;
       
   224 %}
    77 !
   225 !
    78 
   226 
    79 linkToModule
   227 linkToModule
    80     "link this function to the external module.
   228     "link this function to the external module.
    81      I.e. retrieve the module handle and the code pointer."
   229      I.e. retrieve the module handle and the code pointer."
    82 
   230 
    83     |handle code|
   231     |handle code|
    84 
   232 
    85     handle := ObjectFileLoader moduleNamed:moduleName.
   233     moduleName isNil ifTrue:[
       
   234         self error:'Missing moduleName'.
       
   235     ].
       
   236 
       
   237     handle := ObjectFileLoader loadDynamicObject:moduleName.
    86     handle isNil ifTrue:[
   238     handle isNil ifTrue:[
    87         self error:'cannot load: ', moduleName.
   239         self error:'Cannot load module: ', moduleName.
    88     ].
   240     ].
    89     moduleHandle := handle.
   241     moduleHandle := handle.
    90     code := moduleHandle getFunctionAddress:name into:self.
   242     code := moduleHandle getFunctionAddress:name into:self.
    91     code isNil ifTrue:[
   243     code isNil ifTrue:[
    92         self error:'cannot load function: ', name, ' in module: ', moduleName.
   244         self error:'Missing function: ', name, ' in module: ', moduleName.
       
   245     ].
       
   246 !
       
   247 
       
   248 prepareInvoke
       
   249     self hasCode ifFalse:[
       
   250         moduleHandle isNil ifTrue:[
       
   251             self linkToModule.
       
   252             self setupFFI.
       
   253         ].
    93     ].
   254     ].
    94 !
   255 !
    95 
   256 
    96 setupFFI
   257 setupFFI
    97     "setup foreign function interface"
   258     "setup foreign function interface"
    98 
   259 
    99 "
   260 "/    %{
   100 ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
   261 "/    #if defined(WIN32) && defined(i386)
   101                        &ffi_type_uint, args) == FFI_OK
   262 "/        /* Have special code for this case - no need to use of ffi code. */
   102 
   263 "/    #else
   103 "
   264 "/        if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_uint, args)) != FFI_OK)
       
   265 "/    #endif
       
   266 "/    %}
   104 ! !
   267 ! !
   105 
   268 
   106 !ExternalLibraryFunction methodsFor:'private-accessing'!
   269 !ExternalLibraryFunction methodsFor:'private-accessing'!
   107 
   270 
   108 name:functionName module:aModuleName callType:aCallType returnType:aReturnType argumentTypes:argTypes 
   271 name:functionName module:aModuleName callType:aCallType returnType:aReturnType argumentTypes:argTypes 
   114 ! !
   277 ! !
   115 
   278 
   116 !ExternalLibraryFunction class methodsFor:'documentation'!
   279 !ExternalLibraryFunction class methodsFor:'documentation'!
   117 
   280 
   118 version
   281 version
   119     ^ '$Header: /cvs/stx/stx/libbasic/ExternalLibraryFunction.st,v 1.4 2005-06-21 13:17:59 stefan Exp $'
   282     ^ '$Header: /cvs/stx/stx/libbasic/ExternalLibraryFunction.st,v 1.5 2006-04-24 08:49:16 cg Exp $'
   120 ! !
   283 ! !