| 1 | #![doc (html_root_url = "https://docs.rs/libffi-sys/2.3.0" )] |
| 2 | //! Low-level Rust bindings for [libffi](https://sourceware.org/libffi/) |
| 3 | //! |
| 4 | //! The C libffi library provides two main facilities: assembling calls |
| 5 | //! to functions dynamically, and creating closures that can be called |
| 6 | //! as ordinary C functions. |
| 7 | //! |
| 8 | //! This is an undocumented wrapper, originally generated by bindgen then |
| 9 | //! cleaned up manually, intended as the basis for higher-level bindings. |
| 10 | //! |
| 11 | //! See [the libffi crate](https://crates.io/crates/libffi/) for a |
| 12 | //! higher-level API. |
| 13 | //! |
| 14 | //! # Usage |
| 15 | //! |
| 16 | //! `libffi-sys` can either build its own copy of the libffi C library [from |
| 17 | //! github](https://github.com/libffi/libffi) or it can link against your |
| 18 | //! system’s C libffi. By default it builds its own because many systems |
| 19 | //! ship with an old C libffi; this requires that you have a working make, |
| 20 | //! C compiler, automake, and autoconf first. If your system libffi |
| 21 | //! is new enough (v3.2.1 as of October 2019), you can instead enable the |
| 22 | //! `system` feature flag to use that. If you want this crate to build |
| 23 | //! a C libffi for you, add |
| 24 | //! |
| 25 | //! ```toml |
| 26 | //! [dependencies] |
| 27 | //! libffi-sys = "2.3.0" |
| 28 | //! ``` |
| 29 | //! |
| 30 | //! to your `Cargo.toml`. If you want to use your system C libffi, then |
| 31 | //! |
| 32 | //! ```toml |
| 33 | //! [dependencies.libffi-sys] |
| 34 | //! version = "2.3.0" |
| 35 | //! features = ["system"] |
| 36 | //! ``` |
| 37 | //! |
| 38 | //! to your `Cargo.toml` instead. |
| 39 | //! |
| 40 | //! This crate supports Rust version 1.32 and later. |
| 41 | |
| 42 | #![allow (non_camel_case_types)] |
| 43 | #![allow (non_snake_case)] |
| 44 | #![allow (non_upper_case_globals)] |
| 45 | #![allow (improper_ctypes)] |
| 46 | #![allow (unused_imports)] |
| 47 | |
| 48 | use std::fmt::{self, Debug}; |
| 49 | use std::mem::zeroed; |
| 50 | use std::os::raw::{c_char, c_int, c_long, c_schar, c_uint, c_ulong, c_ushort, c_void}; |
| 51 | |
| 52 | mod arch; |
| 53 | pub use arch::*; |
| 54 | use fmt::Formatter; |
| 55 | |
| 56 | pub type ffi_arg = c_ulong; |
| 57 | pub type ffi_sarg = c_long; |
| 58 | pub type ffi_abi = u32; |
| 59 | pub type ffi_status = u32; |
| 60 | pub type ffi_type_enum = u32; |
| 61 | |
| 62 | pub const FFI_64_BIT_MAX: u64 = 9223372036854775807; |
| 63 | pub const FFI_CLOSURES: u32 = 1; |
| 64 | pub const FFI_SIZEOF_ARG: usize = std::mem::size_of::<c_long>(); |
| 65 | // NOTE: This only differs from FFI_SIZEOF_ARG on ILP platforms, which Rust does not support |
| 66 | pub const FFI_SIZEOF_JAVA_RAW: usize = FFI_SIZEOF_ARG; |
| 67 | |
| 68 | pub const FFI_TYPE_VOID: u32 = 0; |
| 69 | pub const FFI_TYPE_INT: u32 = 1; |
| 70 | pub const FFI_TYPE_FLOAT: u32 = 2; |
| 71 | pub const FFI_TYPE_DOUBLE: u32 = 3; |
| 72 | pub const FFI_TYPE_LONGDOUBLE: u32 = 4; |
| 73 | pub const FFI_TYPE_UINT8: u32 = 5; |
| 74 | pub const FFI_TYPE_SINT8: u32 = 6; |
| 75 | pub const FFI_TYPE_UINT16: u32 = 7; |
| 76 | pub const FFI_TYPE_SINT16: u32 = 8; |
| 77 | pub const FFI_TYPE_UINT32: u32 = 9; |
| 78 | pub const FFI_TYPE_SINT32: u32 = 10; |
| 79 | pub const FFI_TYPE_UINT64: u32 = 11; |
| 80 | pub const FFI_TYPE_SINT64: u32 = 12; |
| 81 | pub const FFI_TYPE_STRUCT: u32 = 13; |
| 82 | pub const FFI_TYPE_POINTER: u32 = 14; |
| 83 | pub const FFI_TYPE_COMPLEX: u32 = 15; |
| 84 | pub const FFI_TYPE_LAST: u32 = 15; |
| 85 | |
| 86 | pub const ffi_status_FFI_OK: ffi_status = 0; |
| 87 | pub const ffi_status_FFI_BAD_TYPEDEF: ffi_status = 1; |
| 88 | pub const ffi_status_FFI_BAD_ABI: ffi_status = 2; |
| 89 | pub const ffi_status_FFI_BAD_ARGTYPE: ffi_status = 3; |
| 90 | |
| 91 | pub const ffi_type_enum_STRUCT: ffi_type_enum = 13; |
| 92 | pub const ffi_type_enum_COMPLEX: ffi_type_enum = 15; |
| 93 | |
| 94 | #[repr (C)] |
| 95 | #[derive (Debug, Copy, Clone)] |
| 96 | pub struct ffi_type { |
| 97 | pub size: usize, |
| 98 | pub alignment: c_ushort, |
| 99 | pub type_: c_ushort, |
| 100 | pub elements: *mut *mut ffi_type, |
| 101 | } |
| 102 | |
| 103 | impl Default for ffi_type { |
| 104 | fn default() -> Self { |
| 105 | unsafe { zeroed() } |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | #[repr (C)] |
| 110 | #[derive (Debug, Copy, Clone)] |
| 111 | pub struct ffi_cif { |
| 112 | pub abi: ffi_abi, |
| 113 | pub nargs: c_uint, |
| 114 | pub arg_types: *mut *mut ffi_type, |
| 115 | pub rtype: *mut ffi_type, |
| 116 | pub bytes: c_uint, |
| 117 | pub flags: c_uint, |
| 118 | #[cfg (all(target_arch = "aarch64" , target_os = "windows" ))] |
| 119 | pub is_variadic: c_uint, |
| 120 | #[cfg (all(target_arch = "aarch64" , target_vendor = "apple" ))] |
| 121 | pub aarch64_nfixedargs: c_uint, |
| 122 | #[cfg (all(target_arch = "arm" ))] |
| 123 | pub vfp_used: c_int, |
| 124 | #[cfg (all(target_arch = "arm" ))] |
| 125 | pub vfp_reg_free: c_ushort, |
| 126 | #[cfg (all(target_arch = "arm" ))] |
| 127 | pub vfp_nargs: c_ushort, |
| 128 | #[cfg (all(target_arch = "arm" ))] |
| 129 | pub vfp_args: [c_schar; 16], |
| 130 | #[cfg (any(target_arch = "powerpc" , target_arch = "powerpc64" ))] |
| 131 | pub nfixedargs: c_uint, |
| 132 | #[cfg (any(target_arch = "riscv" , target_arch = "riscv64" ))] |
| 133 | pub riscv_nfixedargs: c_uint, |
| 134 | #[cfg (any(target_arch = "riscv" , target_arch = "riscv64" ))] |
| 135 | pub riscv_unused: c_uint, |
| 136 | #[cfg (all(target_arch = "loongarch64" ))] |
| 137 | pub loongarch_nfixedargs: c_uint, |
| 138 | #[cfg (all(target_arch = "loongarch64" ))] |
| 139 | pub loongarch_unused: c_uint, |
| 140 | } |
| 141 | |
| 142 | impl Default for ffi_cif { |
| 143 | fn default() -> Self { |
| 144 | unsafe { zeroed() } |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | #[repr (C, align(64))] |
| 149 | #[derive (Copy, Clone)] |
| 150 | pub union ffi_raw { |
| 151 | pub sint: ffi_sarg, |
| 152 | pub uint: ffi_arg, |
| 153 | pub flt: f32, |
| 154 | pub data: [c_char; FFI_SIZEOF_ARG], |
| 155 | pub ptr: *mut c_void, |
| 156 | } |
| 157 | |
| 158 | impl Default for ffi_raw { |
| 159 | fn default() -> Self { |
| 160 | unsafe { zeroed() } |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | pub type ffi_java_raw = ffi_raw; |
| 165 | |
| 166 | #[repr (C, align(64))] |
| 167 | #[derive (Copy, Clone)] |
| 168 | pub union ffi_trampoline { |
| 169 | pub tramp: [c_char; FFI_TRAMPOLINE_SIZE], |
| 170 | pub ftramp: *mut c_void, |
| 171 | } |
| 172 | |
| 173 | #[repr (C)] |
| 174 | #[derive (Copy, Clone)] |
| 175 | pub struct ffi_closure { |
| 176 | pub tramp: ffi_trampoline, |
| 177 | pub cif: *mut ffi_cif, |
| 178 | pub fun: Option< |
| 179 | unsafe extern "C" fn( |
| 180 | arg1: *mut ffi_cif, |
| 181 | arg2: *mut c_void, |
| 182 | arg3: *mut *mut c_void, |
| 183 | arg4: *mut c_void, |
| 184 | ), |
| 185 | >, |
| 186 | pub user_data: *mut c_void, |
| 187 | } |
| 188 | |
| 189 | /// Implements Debug manually since sometimes FFI_TRAMPOLINE_SIZE is too large |
| 190 | impl Debug for ffi_closure { |
| 191 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
| 192 | f&mut DebugStruct<'_, '_>.debug_struct("ffi_closure" ) |
| 193 | .field("tramp" , unsafe { &&self.tramp.tramp[..] }) |
| 194 | .field("cif" , &self.cif) |
| 195 | .field("fun" , &self.fun) |
| 196 | .field(name:"user_data" , &self.user_data) |
| 197 | .finish() |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | impl Default for ffi_closure { |
| 202 | fn default() -> Self { |
| 203 | unsafe { zeroed() } |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | #[repr (C)] |
| 208 | #[derive (Copy, Clone)] |
| 209 | pub struct ffi_raw_closure { |
| 210 | pub tramp: [c_char; FFI_TRAMPOLINE_SIZE], |
| 211 | pub cif: *mut ffi_cif, |
| 212 | // See: https://github.com/libffi/libffi/blob/3a7580da73b7f16f275277316d00e3497cbb5a8c/include/ffi.h.in#L364 |
| 213 | #[cfg (not(target_arch = "i686" ))] |
| 214 | pub translate_args: Option< |
| 215 | unsafe extern "C" fn( |
| 216 | arg1: *mut ffi_cif, |
| 217 | arg2: *mut c_void, |
| 218 | arg3: *mut *mut c_void, |
| 219 | arg4: *mut c_void, |
| 220 | ), |
| 221 | >, |
| 222 | #[cfg (not(target_arch = "i686" ))] |
| 223 | pub this_closure: *mut c_void, |
| 224 | pub fun: Option< |
| 225 | unsafe extern "C" fn( |
| 226 | arg1: *mut ffi_cif, |
| 227 | arg2: *mut c_void, |
| 228 | arg3: *mut ffi_raw, |
| 229 | arg4: *mut c_void, |
| 230 | ), |
| 231 | >, |
| 232 | pub user_data: *mut c_void, |
| 233 | } |
| 234 | |
| 235 | /// Implements Debug manually since sometimes FFI_TRAMPOLINE_SIZE is too large |
| 236 | impl Debug for ffi_raw_closure { |
| 237 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
| 238 | let mut debug_struct: DebugStruct<'_, '_> = f.debug_struct(name:"ffi_raw_closure" ); |
| 239 | debug_struct |
| 240 | .field("tramp" , &&self.tramp[..]) |
| 241 | .field(name:"cif" , &self.cif); |
| 242 | |
| 243 | #[cfg (not(target_arch = "i686" ))] |
| 244 | debug_struct.field(name:"translate_args" , &self.translate_args); |
| 245 | #[cfg (not(target_arch = "i686" ))] |
| 246 | debug_struct.field(name:"this_closure" , &self.this_closure); |
| 247 | |
| 248 | debug_struct&mut DebugStruct<'_, '_> |
| 249 | .field("fun" , &self.fun) |
| 250 | .field(name:"user_data" , &self.user_data) |
| 251 | .finish() |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | impl Default for ffi_raw_closure { |
| 256 | fn default() -> Self { |
| 257 | unsafe { zeroed() } |
| 258 | } |
| 259 | } |
| 260 | #[repr (C)] |
| 261 | #[derive (Copy, Clone)] |
| 262 | pub struct ffi_java_raw_closure { |
| 263 | pub tramp: [c_char; FFI_TRAMPOLINE_SIZE], |
| 264 | pub cif: *mut ffi_cif, |
| 265 | // See: https://github.com/libffi/libffi/blob/3a7580da73b7f16f275277316d00e3497cbb5a8c/include/ffi.h.in#L390 |
| 266 | #[cfg (not(target_arch = "i686" ))] |
| 267 | pub translate_args: Option< |
| 268 | unsafe extern "C" fn( |
| 269 | arg1: *mut ffi_cif, |
| 270 | arg2: *mut c_void, |
| 271 | arg3: *mut *mut c_void, |
| 272 | arg4: *mut c_void, |
| 273 | ), |
| 274 | >, |
| 275 | #[cfg (not(target_arch = "i686" ))] |
| 276 | pub this_closure: *mut c_void, |
| 277 | pub fun: Option< |
| 278 | unsafe extern "C" fn( |
| 279 | arg1: *mut ffi_cif, |
| 280 | arg2: *mut c_void, |
| 281 | arg3: *mut ffi_java_raw, |
| 282 | arg4: *mut c_void, |
| 283 | ), |
| 284 | >, |
| 285 | pub user_data: *mut c_void, |
| 286 | } |
| 287 | |
| 288 | /// Implements Debug manually since sometimes FFI_TRAMPOLINE_SIZE is too large |
| 289 | impl Debug for ffi_java_raw_closure { |
| 290 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { |
| 291 | let mut debug_struct: DebugStruct<'_, '_> = f.debug_struct(name:"ffi_java_raw_closure" ); |
| 292 | debug_struct |
| 293 | .field("tramp" , &&self.tramp[..]) |
| 294 | .field(name:"cif" , &self.cif); |
| 295 | |
| 296 | #[cfg (not(target_arch = "i686" ))] |
| 297 | debug_struct.field(name:"translate_args" , &self.translate_args); |
| 298 | #[cfg (not(target_arch = "i686" ))] |
| 299 | debug_struct.field(name:"this_closure" , &self.this_closure); |
| 300 | |
| 301 | debug_struct&mut DebugStruct<'_, '_> |
| 302 | .field("fun" , &self.fun) |
| 303 | .field(name:"user_data" , &self.user_data) |
| 304 | .finish() |
| 305 | } |
| 306 | } |
| 307 | |
| 308 | impl Default for ffi_java_raw_closure { |
| 309 | fn default() -> Self { |
| 310 | unsafe { zeroed() } |
| 311 | } |
| 312 | } |
| 313 | |
| 314 | #[repr (C)] |
| 315 | #[derive (Debug, Copy, Clone)] |
| 316 | pub struct ffi_go_closure { |
| 317 | pub tramp: *mut c_void, |
| 318 | pub cif: *mut ffi_cif, |
| 319 | pub fun: Option< |
| 320 | unsafe extern "C" fn( |
| 321 | arg1: *mut ffi_cif, |
| 322 | arg2: *mut c_void, |
| 323 | arg3: *mut *mut c_void, |
| 324 | arg4: *mut c_void, |
| 325 | ), |
| 326 | >, |
| 327 | } |
| 328 | impl Default for ffi_go_closure { |
| 329 | fn default() -> Self { |
| 330 | unsafe { zeroed() } |
| 331 | } |
| 332 | } |
| 333 | |
| 334 | unsafeextern "C" { |
| 335 | pub unsafestatic mut ffi_type_void: ffi_type; |
| 336 | pub unsafestatic mut ffi_type_uint8: ffi_type; |
| 337 | pub unsafestatic mut ffi_type_sint8: ffi_type; |
| 338 | pub unsafestatic mut ffi_type_uint16: ffi_type; |
| 339 | pub unsafestatic mut ffi_type_sint16: ffi_type; |
| 340 | pub unsafestatic mut ffi_type_uint32: ffi_type; |
| 341 | pub unsafestatic mut ffi_type_sint32: ffi_type; |
| 342 | pub unsafestatic mut ffi_type_uint64: ffi_type; |
| 343 | pub unsafestatic mut ffi_type_sint64: ffi_type; |
| 344 | pub unsafestatic mut ffi_type_float: ffi_type; |
| 345 | pub unsafestatic mut ffi_type_double: ffi_type; |
| 346 | pub unsafestatic mut ffi_type_pointer: ffi_type; |
| 347 | |
| 348 | #[cfg (not(target_arch = "aarch64" ))] |
| 349 | #[cfg (not(all(target_arch = "arm" , target_os = "linux" , target_env = "gnu" )))] |
| 350 | pub unsafestatic mut ffi_type_longdouble: ffi_type; |
| 351 | |
| 352 | #[cfg (feature = "complex" )] |
| 353 | pub static mut ffi_type_complex_float: ffi_type; |
| 354 | |
| 355 | #[cfg (feature = "complex" )] |
| 356 | pub static mut ffi_type_complex_double: ffi_type; |
| 357 | |
| 358 | #[cfg (feature = "complex" )] |
| 359 | #[cfg (not(all(target_arch = "arm" , target_os = "linux" , target_env = "gnu" )))] |
| 360 | pub static mut ffi_type_complex_longdouble: ffi_type; |
| 361 | |
| 362 | pub unsafefn ffi_raw_call( |
| 363 | cif: *mut ffi_cif, |
| 364 | fn_: Option<unsafe extern "C" fn()>, |
| 365 | rvalue: *mut c_void, |
| 366 | avalue: *mut ffi_raw, |
| 367 | ); |
| 368 | |
| 369 | pub unsafefn ffi_ptrarray_to_raw(cif: *mut ffi_cif, args: *mut *mut c_void, raw: *mut ffi_raw); |
| 370 | |
| 371 | pub unsafefn ffi_raw_to_ptrarray(cif: *mut ffi_cif, raw: *mut ffi_raw, args: *mut *mut c_void); |
| 372 | |
| 373 | pub unsafefn ffi_raw_size(cif: *mut ffi_cif) -> usize; |
| 374 | |
| 375 | // See: https://github.com/libffi/libffi/blob/3a7580da73b7f16f275277316d00e3497cbb5a8c/include/ffi.h.in#L286 |
| 376 | #[cfg (not(target_arch = "i686" ))] |
| 377 | pub unsafefn ffi_java_raw_call( |
| 378 | cif: *mut ffi_cif, |
| 379 | fn_: Option<unsafe extern "C" fn()>, |
| 380 | rvalue: *mut c_void, |
| 381 | avalue: *mut ffi_java_raw, |
| 382 | ); |
| 383 | |
| 384 | pub unsafefn ffi_java_ptrarray_to_raw( |
| 385 | cif: *mut ffi_cif, |
| 386 | args: *mut *mut c_void, |
| 387 | raw: *mut ffi_java_raw, |
| 388 | ); |
| 389 | |
| 390 | pub unsafefn ffi_java_raw_to_ptrarray( |
| 391 | cif: *mut ffi_cif, |
| 392 | raw: *mut ffi_java_raw, |
| 393 | args: *mut *mut c_void, |
| 394 | ); |
| 395 | |
| 396 | pub unsafefn ffi_java_raw_size(cif: *mut ffi_cif) -> usize; |
| 397 | |
| 398 | pub unsafefn ffi_closure_alloc(size: usize, code: *mut *mut c_void) -> *mut c_void; |
| 399 | |
| 400 | pub unsafefn ffi_closure_free(arg1: *mut c_void); |
| 401 | |
| 402 | pub unsafefn ffi_prep_closure( |
| 403 | arg1: *mut ffi_closure, |
| 404 | arg2: *mut ffi_cif, |
| 405 | fun: Option< |
| 406 | unsafe extern "C" fn( |
| 407 | arg1: *mut ffi_cif, |
| 408 | arg2: *mut c_void, |
| 409 | arg3: *mut *mut c_void, |
| 410 | arg4: *mut c_void, |
| 411 | ), |
| 412 | >, |
| 413 | user_data: *mut c_void, |
| 414 | ) -> ffi_status; |
| 415 | |
| 416 | pub unsafefn ffi_prep_closure_loc( |
| 417 | arg1: *mut ffi_closure, |
| 418 | arg2: *mut ffi_cif, |
| 419 | fun: Option< |
| 420 | unsafe extern "C" fn( |
| 421 | arg1: *mut ffi_cif, |
| 422 | arg2: *mut c_void, |
| 423 | arg3: *mut *mut c_void, |
| 424 | arg4: *mut c_void, |
| 425 | ), |
| 426 | >, |
| 427 | user_data: *mut c_void, |
| 428 | codeloc: *mut c_void, |
| 429 | ) -> ffi_status; |
| 430 | |
| 431 | pub unsafefn ffi_prep_raw_closure( |
| 432 | arg1: *mut ffi_raw_closure, |
| 433 | cif: *mut ffi_cif, |
| 434 | fun: Option< |
| 435 | unsafe extern "C" fn( |
| 436 | arg1: *mut ffi_cif, |
| 437 | arg2: *mut c_void, |
| 438 | arg3: *mut ffi_raw, |
| 439 | arg4: *mut c_void, |
| 440 | ), |
| 441 | >, |
| 442 | user_data: *mut c_void, |
| 443 | ) -> ffi_status; |
| 444 | |
| 445 | pub unsafefn ffi_prep_raw_closure_loc( |
| 446 | arg1: *mut ffi_raw_closure, |
| 447 | cif: *mut ffi_cif, |
| 448 | fun: Option< |
| 449 | unsafe extern "C" fn( |
| 450 | arg1: *mut ffi_cif, |
| 451 | arg2: *mut c_void, |
| 452 | arg3: *mut ffi_raw, |
| 453 | arg4: *mut c_void, |
| 454 | ), |
| 455 | >, |
| 456 | user_data: *mut c_void, |
| 457 | codeloc: *mut c_void, |
| 458 | ) -> ffi_status; |
| 459 | |
| 460 | // See: https://github.com/libffi/libffi/blob/3a7580da73b7f16f275277316d00e3497cbb5a8c/include/ffi.h.in#L419 |
| 461 | #[cfg (not(target_arch = "i686" ))] |
| 462 | pub unsafefn ffi_prep_java_raw_closure( |
| 463 | arg1: *mut ffi_java_raw_closure, |
| 464 | cif: *mut ffi_cif, |
| 465 | fun: Option< |
| 466 | unsafe extern "C" fn( |
| 467 | arg1: *mut ffi_cif, |
| 468 | arg2: *mut c_void, |
| 469 | arg3: *mut ffi_java_raw, |
| 470 | arg4: *mut c_void, |
| 471 | ), |
| 472 | >, |
| 473 | user_data: *mut c_void, |
| 474 | ) -> ffi_status; |
| 475 | |
| 476 | // See: https://github.com/libffi/libffi/blob/3a7580da73b7f16f275277316d00e3497cbb5a8c/include/ffi.h.in#L419 |
| 477 | #[cfg (not(target_arch = "i686" ))] |
| 478 | pub unsafefn ffi_prep_java_raw_closure_loc( |
| 479 | arg1: *mut ffi_java_raw_closure, |
| 480 | cif: *mut ffi_cif, |
| 481 | fun: Option< |
| 482 | unsafe extern "C" fn( |
| 483 | arg1: *mut ffi_cif, |
| 484 | arg2: *mut c_void, |
| 485 | arg3: *mut ffi_java_raw, |
| 486 | arg4: *mut c_void, |
| 487 | ), |
| 488 | >, |
| 489 | user_data: *mut c_void, |
| 490 | codeloc: *mut c_void, |
| 491 | ) -> ffi_status; |
| 492 | |
| 493 | pub unsafefn ffi_prep_go_closure( |
| 494 | arg1: *mut ffi_go_closure, |
| 495 | arg2: *mut ffi_cif, |
| 496 | fun: Option< |
| 497 | unsafe extern "C" fn( |
| 498 | arg1: *mut ffi_cif, |
| 499 | arg2: *mut c_void, |
| 500 | arg3: *mut *mut c_void, |
| 501 | arg4: *mut c_void, |
| 502 | ), |
| 503 | >, |
| 504 | ) -> ffi_status; |
| 505 | |
| 506 | pub unsafefn ffi_call_go( |
| 507 | cif: *mut ffi_cif, |
| 508 | fn_: Option<unsafe extern "C" fn()>, |
| 509 | rvalue: *mut c_void, |
| 510 | avalue: *mut *mut c_void, |
| 511 | closure: *mut c_void, |
| 512 | ); |
| 513 | |
| 514 | pub unsafefn ffi_prep_cif( |
| 515 | cif: *mut ffi_cif, |
| 516 | abi: ffi_abi, |
| 517 | nargs: c_uint, |
| 518 | rtype: *mut ffi_type, |
| 519 | atypes: *mut *mut ffi_type, |
| 520 | ) -> ffi_status; |
| 521 | |
| 522 | pub unsafefn ffi_prep_cif_var( |
| 523 | cif: *mut ffi_cif, |
| 524 | abi: ffi_abi, |
| 525 | nfixedargs: c_uint, |
| 526 | ntotalargs: c_uint, |
| 527 | rtype: *mut ffi_type, |
| 528 | atypes: *mut *mut ffi_type, |
| 529 | ) -> ffi_status; |
| 530 | |
| 531 | pub unsafefn ffi_call( |
| 532 | cif: *mut ffi_cif, |
| 533 | fn_: Option<unsafe extern "C" fn()>, |
| 534 | rvalue: *mut c_void, |
| 535 | avalue: *mut *mut c_void, |
| 536 | ); |
| 537 | |
| 538 | pub unsafefn ffi_get_struct_offsets( |
| 539 | abi: ffi_abi, |
| 540 | struct_type: *mut ffi_type, |
| 541 | offsets: *mut usize, |
| 542 | ) -> ffi_status; |
| 543 | } |
| 544 | |
| 545 | #[cfg (test)] |
| 546 | mod test { |
| 547 | use super::*; |
| 548 | |
| 549 | extern "C" fn add(x: u64, y: u64) -> u64 { |
| 550 | x + y |
| 551 | } |
| 552 | |
| 553 | #[test ] |
| 554 | fn test_function_with_two_arguments() { |
| 555 | unsafe { |
| 556 | let mut cif: ffi_cif = Default::default(); |
| 557 | let mut arg_types: Vec<*mut ffi_type> = |
| 558 | vec![&mut ffi_type_uint64, &mut ffi_type_uint64]; |
| 559 | |
| 560 | let prep_status = ffi_prep_cif( |
| 561 | &mut cif, |
| 562 | ffi_abi_FFI_DEFAULT_ABI, |
| 563 | 2, |
| 564 | &mut ffi_type_uint64, |
| 565 | arg_types.as_mut_ptr(), |
| 566 | ); |
| 567 | |
| 568 | assert_eq!(prep_status, ffi_status_FFI_OK); |
| 569 | |
| 570 | let mut rval = 0u64; |
| 571 | let func = &*(&(add as *mut extern "C" fn(u64, u64) -> u64) as *const _ |
| 572 | as *const extern "C" fn()); |
| 573 | |
| 574 | ffi_call( |
| 575 | &mut cif, |
| 576 | Some(*func), |
| 577 | &mut rval as *mut _ as *mut c_void, |
| 578 | vec![ |
| 579 | &mut 4u64 as *mut _ as *mut c_void, |
| 580 | &mut 5u64 as *mut _ as *mut c_void, |
| 581 | ] |
| 582 | .as_mut_ptr(), |
| 583 | ); |
| 584 | |
| 585 | assert_eq!(rval, 9); |
| 586 | } |
| 587 | } |
| 588 | } |
| 589 | |