1#![doc(html_root_url = "https://docs.rs/libffi-sys/1.1.1")]
2#![allow(non_camel_case_types)]
45#![allow(non_snake_case)]
46#![allow(non_upper_case_globals)]
47#![allow(improper_ctypes)]
48#![allow(unused_imports)]
49
50use std::fmt::{self, Debug};
51use std::mem::zeroed;
52use std::os::raw::{c_char, c_int, c_long, c_schar, c_uint, c_ulong, c_ushort, c_void};
53
54mod arch;
55pub use arch::*;
56use fmt::Formatter;
57
58pub type ffi_arg = c_ulong;
59pub type ffi_sarg = c_long;
60pub type ffi_abi = u32;
61pub type ffi_status = u32;
62pub type ffi_type_enum = u32;
63
64pub const FFI_64_BIT_MAX: u64 = 9223372036854775807;
65pub const FFI_CLOSURES: u32 = 1;
66pub const FFI_SIZEOF_ARG: usize = std::mem::size_of::<c_long>();
67pub const FFI_SIZEOF_JAVA_RAW: usize = FFI_SIZEOF_ARG;
69
70pub const FFI_TYPE_VOID: u32 = 0;
71pub const FFI_TYPE_INT: u32 = 1;
72pub const FFI_TYPE_FLOAT: u32 = 2;
73pub const FFI_TYPE_DOUBLE: u32 = 3;
74pub const FFI_TYPE_LONGDOUBLE: u32 = 4;
75pub const FFI_TYPE_UINT8: u32 = 5;
76pub const FFI_TYPE_SINT8: u32 = 6;
77pub const FFI_TYPE_UINT16: u32 = 7;
78pub const FFI_TYPE_SINT16: u32 = 8;
79pub const FFI_TYPE_UINT32: u32 = 9;
80pub const FFI_TYPE_SINT32: u32 = 10;
81pub const FFI_TYPE_UINT64: u32 = 11;
82pub const FFI_TYPE_SINT64: u32 = 12;
83pub const FFI_TYPE_STRUCT: u32 = 13;
84pub const FFI_TYPE_POINTER: u32 = 14;
85pub const FFI_TYPE_COMPLEX: u32 = 15;
86pub const FFI_TYPE_LAST: u32 = 15;
87
88pub const ffi_status_FFI_OK: ffi_status = 0;
89pub const ffi_status_FFI_BAD_TYPEDEF: ffi_status = 1;
90pub const ffi_status_FFI_BAD_ABI: ffi_status = 2;
91
92pub const ffi_type_enum_STRUCT: ffi_type_enum = 13;
93pub const ffi_type_enum_COMPLEX: ffi_type_enum = 15;
94
95#[repr(C)]
96#[derive(Debug, Copy, Clone)]
97pub struct ffi_type {
98 pub size: usize,
99 pub alignment: c_ushort,
100 pub type_: c_ushort,
101 pub elements: *mut *mut ffi_type,
102}
103
104impl Default for ffi_type {
105 fn default() -> Self {
106 unsafe { zeroed() }
107 }
108}
109
110#[repr(C)]
111#[derive(Debug, Copy, Clone)]
112pub struct ffi_cif {
113 pub abi: ffi_abi,
114 pub nargs: c_uint,
115 pub arg_types: *mut *mut ffi_type,
116 pub rtype: *mut ffi_type,
117 pub bytes: c_uint,
118 pub flags: c_uint,
119 #[cfg(all(target_arch = "aarch64", target_os = "windows"))]
120 pub is_variadic: c_uint,
121 #[cfg(all(target_arch = "aarch64", target_vendor = "apple"))]
122 pub aarch64_nfixedargs: c_uint,
123 #[cfg(all(target_arch = "arm"))]
124 pub vfp_used: c_int,
125 #[cfg(all(target_arch = "arm"))]
126 pub vfp_reg_free: c_ushort,
127 #[cfg(all(target_arch = "arm"))]
128 pub vfp_nargs: c_ushort,
129 #[cfg(all(target_arch = "arm"))]
130 pub vfp_args: [c_schar; 16],
131 #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
132 pub nfixedargs: c_uint,
133}
134
135impl Default for ffi_cif {
136 fn default() -> Self {
137 unsafe { zeroed() }
138 }
139}
140
141#[repr(C)]
142#[derive(Copy, Clone)]
143pub union ffi_raw {
144 pub sint: ffi_sarg,
145 pub uint: ffi_arg,
146 pub flt: f32,
147 pub data: [c_char; FFI_SIZEOF_ARG],
148 pub ptr: *mut c_void,
149 _bindgen_union_align: u64,
150}
151
152impl Default for ffi_raw {
153 fn default() -> Self {
154 unsafe { zeroed() }
155 }
156}
157
158pub type ffi_java_raw = ffi_raw;
159
160#[repr(C)]
161#[derive(Copy, Clone)]
162pub struct ffi_closure {
163 pub tramp: [c_char; FFI_TRAMPOLINE_SIZE],
164 pub cif: *mut ffi_cif,
165 pub fun: Option<
166 unsafe extern "C" fn(
167 arg1: *mut ffi_cif,
168 arg2: *mut c_void,
169 arg3: *mut *mut c_void,
170 arg4: *mut c_void,
171 ),
172 >,
173 pub user_data: *mut c_void,
174}
175
176impl Debug for ffi_closure {
178 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
179 f.debug_struct("ffi_closure")
180 .field("tramp", &&self.tramp[..])
181 .field("cif", &self.cif)
182 .field("fun", &self.fun)
183 .field("user_data", &self.user_data)
184 .finish()
185 }
186}
187
188impl Default for ffi_closure {
189 fn default() -> Self {
190 unsafe { zeroed() }
191 }
192}
193
194#[repr(C)]
195#[derive(Copy, Clone)]
196pub struct ffi_raw_closure {
197 pub tramp: [c_char; FFI_TRAMPOLINE_SIZE],
198 pub cif: *mut ffi_cif,
199 #[cfg(not(target_arch = "i686"))]
201 pub translate_args: Option<
202 unsafe extern "C" fn(
203 arg1: *mut ffi_cif,
204 arg2: *mut c_void,
205 arg3: *mut *mut c_void,
206 arg4: *mut c_void,
207 ),
208 >,
209 #[cfg(not(target_arch = "i686"))]
210 pub this_closure: *mut c_void,
211 pub fun: Option<
212 unsafe extern "C" fn(
213 arg1: *mut ffi_cif,
214 arg2: *mut c_void,
215 arg3: *mut ffi_raw,
216 arg4: *mut c_void,
217 ),
218 >,
219 pub user_data: *mut c_void,
220}
221
222impl Debug for ffi_raw_closure {
224 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
225 let mut debug_struct = f.debug_struct("ffi_raw_closure");
226 debug_struct
227 .field("tramp", &&self.tramp[..])
228 .field("cif", &self.cif);
229
230 #[cfg(not(target_arch = "i686"))]
231 debug_struct.field("translate_args", &self.translate_args);
232 #[cfg(not(target_arch = "i686"))]
233 debug_struct.field("this_closure", &self.this_closure);
234
235 debug_struct
236 .field("fun", &self.fun)
237 .field("user_data", &self.user_data)
238 .finish()
239 }
240}
241
242impl Default for ffi_raw_closure {
243 fn default() -> Self {
244 unsafe { zeroed() }
245 }
246}
247#[repr(C)]
248#[derive(Copy, Clone)]
249pub struct ffi_java_raw_closure {
250 pub tramp: [c_char; FFI_TRAMPOLINE_SIZE],
251 pub cif: *mut ffi_cif,
252 #[cfg(not(target_arch = "i686"))]
254 pub translate_args: Option<
255 unsafe extern "C" fn(
256 arg1: *mut ffi_cif,
257 arg2: *mut c_void,
258 arg3: *mut *mut c_void,
259 arg4: *mut c_void,
260 ),
261 >,
262 #[cfg(not(target_arch = "i686"))]
263 pub this_closure: *mut c_void,
264 pub fun: Option<
265 unsafe extern "C" fn(
266 arg1: *mut ffi_cif,
267 arg2: *mut c_void,
268 arg3: *mut ffi_java_raw,
269 arg4: *mut c_void,
270 ),
271 >,
272 pub user_data: *mut c_void,
273}
274
275impl Debug for ffi_java_raw_closure {
277 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
278 let mut debug_struct = f.debug_struct("ffi_java_raw_closure");
279 debug_struct
280 .field("tramp", &&self.tramp[..])
281 .field("cif", &self.cif);
282
283 #[cfg(not(target_arch = "i686"))]
284 debug_struct.field("translate_args", &self.translate_args);
285 #[cfg(not(target_arch = "i686"))]
286 debug_struct.field("this_closure", &self.this_closure);
287
288 debug_struct
289 .field("fun", &self.fun)
290 .field("user_data", &self.user_data)
291 .finish()
292 }
293}
294
295impl Default for ffi_java_raw_closure {
296 fn default() -> Self {
297 unsafe { zeroed() }
298 }
299}
300
301#[repr(C)]
302#[derive(Debug, Copy, Clone)]
303pub struct ffi_go_closure {
304 pub tramp: *mut c_void,
305 pub cif: *mut ffi_cif,
306 pub fun: Option<
307 unsafe extern "C" fn(
308 arg1: *mut ffi_cif,
309 arg2: *mut c_void,
310 arg3: *mut *mut c_void,
311 arg4: *mut c_void,
312 ),
313 >,
314}
315impl Default for ffi_go_closure {
316 fn default() -> Self {
317 unsafe { zeroed() }
318 }
319}
320
321extern "C" {
322 pub static mut ffi_type_void: ffi_type;
323 pub static mut ffi_type_uint8: ffi_type;
324 pub static mut ffi_type_sint8: ffi_type;
325 pub static mut ffi_type_uint16: ffi_type;
326 pub static mut ffi_type_sint16: ffi_type;
327 pub static mut ffi_type_uint32: ffi_type;
328 pub static mut ffi_type_sint32: ffi_type;
329 pub static mut ffi_type_uint64: ffi_type;
330 pub static mut ffi_type_sint64: ffi_type;
331 pub static mut ffi_type_float: ffi_type;
332 pub static mut ffi_type_double: ffi_type;
333 pub static mut ffi_type_pointer: ffi_type;
334
335 #[cfg(not(all(target_arch = "arm", target_os = "linux", target_env = "gnu")))]
336 pub static mut ffi_type_longdouble: ffi_type;
337
338 #[cfg(feature = "complex")]
339 pub static mut ffi_type_complex_float: ffi_type;
340
341 #[cfg(feature = "complex")]
342 pub static mut ffi_type_complex_double: ffi_type;
343
344 #[cfg(feature = "complex")]
345 #[cfg(not(all(target_arch = "arm", target_os = "linux", target_env = "gnu")))]
346 pub static mut ffi_type_complex_longdouble: ffi_type;
347
348 pub fn ffi_raw_call(
349 cif: *mut ffi_cif,
350 fn_: Option<unsafe extern "C" fn()>,
351 rvalue: *mut c_void,
352 avalue: *mut ffi_raw,
353 );
354
355 pub fn ffi_ptrarray_to_raw(cif: *mut ffi_cif, args: *mut *mut c_void, raw: *mut ffi_raw);
356
357 pub fn ffi_raw_to_ptrarray(cif: *mut ffi_cif, raw: *mut ffi_raw, args: *mut *mut c_void);
358
359 pub fn ffi_raw_size(cif: *mut ffi_cif) -> usize;
360
361 #[cfg(not(target_arch = "i686"))]
363 pub fn ffi_java_raw_call(
364 cif: *mut ffi_cif,
365 fn_: Option<unsafe extern "C" fn()>,
366 rvalue: *mut c_void,
367 avalue: *mut ffi_java_raw,
368 );
369
370 pub fn ffi_java_ptrarray_to_raw(
371 cif: *mut ffi_cif,
372 args: *mut *mut c_void,
373 raw: *mut ffi_java_raw,
374 );
375
376 pub fn ffi_java_raw_to_ptrarray(
377 cif: *mut ffi_cif,
378 raw: *mut ffi_java_raw,
379 args: *mut *mut c_void,
380 );
381
382 pub fn ffi_java_raw_size(cif: *mut ffi_cif) -> usize;
383
384 pub fn ffi_closure_alloc(size: usize, code: *mut *mut c_void) -> *mut c_void;
385
386 pub fn ffi_closure_free(arg1: *mut c_void);
387
388 pub fn ffi_prep_closure(
389 arg1: *mut ffi_closure,
390 arg2: *mut ffi_cif,
391 fun: Option<
392 unsafe extern "C" fn(
393 arg1: *mut ffi_cif,
394 arg2: *mut c_void,
395 arg3: *mut *mut c_void,
396 arg4: *mut c_void,
397 ),
398 >,
399 user_data: *mut c_void,
400 ) -> ffi_status;
401
402 pub fn ffi_prep_closure_loc(
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 codeloc: *mut c_void,
415 ) -> ffi_status;
416
417 pub fn ffi_prep_raw_closure(
418 arg1: *mut ffi_raw_closure,
419 cif: *mut ffi_cif,
420 fun: Option<
421 unsafe extern "C" fn(
422 arg1: *mut ffi_cif,
423 arg2: *mut c_void,
424 arg3: *mut ffi_raw,
425 arg4: *mut c_void,
426 ),
427 >,
428 user_data: *mut c_void,
429 ) -> ffi_status;
430
431 pub fn ffi_prep_raw_closure_loc(
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 codeloc: *mut c_void,
444 ) -> ffi_status;
445
446 #[cfg(not(target_arch = "i686"))]
448 pub fn ffi_prep_java_raw_closure(
449 arg1: *mut ffi_java_raw_closure,
450 cif: *mut ffi_cif,
451 fun: Option<
452 unsafe extern "C" fn(
453 arg1: *mut ffi_cif,
454 arg2: *mut c_void,
455 arg3: *mut ffi_java_raw,
456 arg4: *mut c_void,
457 ),
458 >,
459 user_data: *mut c_void,
460 ) -> ffi_status;
461
462 #[cfg(not(target_arch = "i686"))]
464 pub fn ffi_prep_java_raw_closure_loc(
465 arg1: *mut ffi_java_raw_closure,
466 cif: *mut ffi_cif,
467 fun: Option<
468 unsafe extern "C" fn(
469 arg1: *mut ffi_cif,
470 arg2: *mut c_void,
471 arg3: *mut ffi_java_raw,
472 arg4: *mut c_void,
473 ),
474 >,
475 user_data: *mut c_void,
476 codeloc: *mut c_void,
477 ) -> ffi_status;
478
479 pub fn ffi_prep_go_closure(
480 arg1: *mut ffi_go_closure,
481 arg2: *mut ffi_cif,
482 fun: Option<
483 unsafe extern "C" fn(
484 arg1: *mut ffi_cif,
485 arg2: *mut c_void,
486 arg3: *mut *mut c_void,
487 arg4: *mut c_void,
488 ),
489 >,
490 ) -> ffi_status;
491
492 pub fn ffi_call_go(
493 cif: *mut ffi_cif,
494 fn_: Option<unsafe extern "C" fn()>,
495 rvalue: *mut c_void,
496 avalue: *mut *mut c_void,
497 closure: *mut c_void,
498 );
499
500 pub fn ffi_prep_cif(
501 cif: *mut ffi_cif,
502 abi: ffi_abi,
503 nargs: c_uint,
504 rtype: *mut ffi_type,
505 atypes: *mut *mut ffi_type,
506 ) -> ffi_status;
507
508 pub fn ffi_prep_cif_var(
509 cif: *mut ffi_cif,
510 abi: ffi_abi,
511 nfixedargs: c_uint,
512 ntotalargs: c_uint,
513 rtype: *mut ffi_type,
514 atypes: *mut *mut ffi_type,
515 ) -> ffi_status;
516
517 pub fn ffi_call(
518 cif: *mut ffi_cif,
519 fn_: Option<unsafe extern "C" fn()>,
520 rvalue: *mut c_void,
521 avalue: *mut *mut c_void,
522 );
523
524 pub fn ffi_get_struct_offsets(
525 abi: ffi_abi,
526 struct_type: *mut ffi_type,
527 offsets: *mut usize,
528 ) -> ffi_status;
529}
530
531#[cfg(test)]
532mod test {
533 use super::*;
534
535 extern "C" fn add(x: u64, y: u64) -> u64 {
536 x + y
537 }
538
539 #[test]
540 fn test_function_with_two_arguments() {
541 unsafe {
542 let mut cif: ffi_cif = Default::default();
543 let mut arg_types: Vec<*mut ffi_type> =
544 vec![&mut ffi_type_uint64, &mut ffi_type_uint64];
545
546 let prep_status = ffi_prep_cif(
547 &mut cif,
548 ffi_abi_FFI_DEFAULT_ABI,
549 2,
550 &mut ffi_type_uint64,
551 arg_types.as_mut_ptr(),
552 );
553
554 assert_eq!(prep_status, ffi_status_FFI_OK);
555
556 let mut rval = 0u64;
557 let func = &*(&(add as *mut extern "C" fn(u64, u64) -> u64) as *const _
558 as *const extern "C" fn());
559
560 ffi_call(
561 &mut cif,
562 Some(*func),
563 &mut rval as *mut _ as *mut c_void,
564 vec![
565 &mut 4u64 as *mut _ as *mut c_void,
566 &mut 5u64 as *mut _ as *mut c_void,
567 ]
568 .as_mut_ptr(),
569 );
570
571 assert_eq!(rval, 9);
572 }
573 }
574}