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