/src/wrappers/ffi/library/ffi_call.e
Specman e | 132 lines | 56 code | 10 blank | 66 comment | 2 complexity | f96d1dc1a797e2a7d1fc1fe199718082 MD5 | raw file
1class FFI_CALL 2-- A Foreign Function Interface call. 3-- Libffi' assumes that you have a pointer to the function you wish to 4-- call and that you know the number and types of arguments to pass it, as 5-- well as the return type of the function. 6-- The first thing you must do is create an ffi_cif object that matches 7-- the signature of the function you wish to call. This is a separate step 8-- because it is common to make multiple calls using a single ffi_cif. The 9-- cif in ffi_cif stands for Call InterFace. To prepare a call interface 10-- object, use the function ffi_prep_cif. 11 12inherit 13 C_STRUCT 14 EIFFEL_OWNED 15 16insert 17 FFI_TYPES 18 FFI_CIF_STRUCT 19 FFI_EXTERNALS 20 FFI_MORE_EXTERNALS -- this is hand-written, those other inserts are generated 21 22create {ANY} 23 prepare 24 25feature {ANY} -- Preparation of a call 26 prepare (a_function: POINTER; a_return_type: POINTER; some_argument_types: ARRAYED_COLLECTION[POINTER]) 27 -- Initializes Current call according to the given parameters. 28 -- Functions with variable number of arguments (also known as varargs) are not supported. 29 -- `a_return_type' must be a pointer to an ffi_type structure that describes the return type of the function. See FFI_TYPES. 30 -- `some_argument_types' contains the types of arguments. May be Void 31 -- FFI allows to use several different ABI conventions, but they are highly 32 -- platform-dependent. TODO: support different ABIs. 33 -- `status' is updated and will be either is_ok if everything worked 34 -- properly; is_bad__abi if the ABI is invalid (see above); its value may 35 -- be "FFI_BAD_TYPEDEF" if one of the arguments is incorrect; TODO: this 36 -- value should belong to FFI_STATUSENUM but currently it is not found in 37 -- the code. 38 require 39 a_function.is_not_null 40 a_return_type.is_not_null 41 some_argument_types /= Void implies not some_argument_types.is_empty 42 -- TODO: reactivate the following preconditions when they will not make the compiler produce wrong code anymore. Paolo 2010-03-19 43 -- is_valid_type(a_return_type) 44 -- some_argument_types=Void or else 45 -- some_argument_types.for_all(agent is_valid_type) 46 local 47 args: POINTER; count: NATURAL_32 48 do 49 handle := malloc(struct_size) -- Also allocate works 50 function := a_function 51 argument_types := some_argument_types 52 if argument_types /= Void then 53 args := argument_types.to_external 54 count := argument_types.count.to_natural_32 55 else 56 check 57 args.is_null 58 count = 0.to_natural_32 59 end 60 end 61 status.change_value(ffi_prep_cif(handle, default_abi, count, a_return_type, args)) 62 check 63 not status.is_bad_abi 64 end 65 ensure 66 function_set: function = a_function 67 -- Note: someone may want to turn this into invariant Actually they 68 -- are right, it is an invariant. But since we do not offer a feature 69 -- to change function value we only need to check that this creation 70 -- feature correctly set it. 71 end 72 73 invoke (a_result: POINTER; some_values: ARRAYED_COLLECTION[POINTER]) 74 -- Calls `function' according to the description of Current. 75 -- `a_result' shall point to a chunk of memory that will hold the 76 -- result of the function call. This must be large enough to hold the 77 -- result and must be suitably aligned; it is the caller's 78 -- responsibility to ensure this. If Current declares that the function 79 -- returns void (using ffi_type_void), then `a_result' is ignored. If 80 -- `a_result' is NULL then the return value is discarded. 81 -- `some_values' shall point to a vector of "void *" pointers that 82 -- point to the memory locations holding the argument values for a 83 -- call. If Current declares that the function has no arguments (i.e., 84 -- nargs was 0), then avalues is ignored. 85 -- TODO: reactivate the following preconditions when they will not make the compiler produce wrong code anymore. Paolo 2010-03-19 86 -- require 87 -- parameterless_shall_be_called_without_parameters: some_values=Void implies argument_types=Void 88 -- correct_number_of_paramenters: some_values/=Void implies argument_types.count = some_values.count 89 local 90 h, f, r, v: POINTER 91 do 92 h := handle 93 f := function 94 r := a_result 95 if some_values /= Void then 96 v := some_values.to_external 97 end 98 ffi_call(h, f, r, v) 99 end 100 101feature {ANY} -- Status 102 status: FFI_STATUS_ENUM 103 -- The status of Current call. 104 105 function: POINTER 106 -- The address of the function that will be called 107 108 argument_types: ARRAYED_COLLECTION[POINTER] 109 -- Pointers to the structures describing the function that will be called 110 111end -- class FFI_CALL 112 113-- Liberty Eiffel FFI wrappers - Copyright (C) 2012-2017: Cyril Adrian, Paolo Redaelli 114-- 115-- Permission is hereby granted, free of charge, to any person obtaining 116-- a copy of this software and associated documentation files (the 117-- ``Software''), to deal in the Software without restriction, including 118-- without limitation the rights to use, copy, modify, merge, publish, 119-- distribute, sublicense, and/or sell copies of the Software, and to 120-- permit persons to whom the Software is furnished to do so, subject to 121-- the following conditions: 122-- 123-- The above copyright notice and this permission notice shall be included 124-- in all copies or substantial portions of the Software. 125-- 126-- THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 127-- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 128-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 129-- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 130-- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 131-- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 132-- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.