qemu_plugin/glib/
mod.rs

1//! GLib FFI bindings
2
3#[cfg(not(any(feature = "plugin-api-v0", feature = "plugin-api-v1")))]
4use crate::sys::{GArray, GByteArray};
5use std::ffi::c_void;
6
7#[cfg(not(windows))]
8unsafe extern "C" {
9    /// glib g_free is provided by the QEMU program we are being linked into
10    pub(crate) fn g_free(mem: *mut c_void);
11}
12
13#[cfg(all(
14    not(windows),
15    not(any(feature = "plugin-api-v0", feature = "plugin-api-v1"))
16))]
17unsafe extern "C" {
18    /// glib g_byte_array_new is provided by the QEMU program we are being linked into
19    pub(crate) fn g_byte_array_new() -> *mut GByteArray;
20    /// glib g_byte_array_free is provided by the QEMU program we are being linked into
21    pub(crate) fn g_byte_array_free(array: *mut GByteArray, free_segment: bool) -> *mut u8;
22    /// glib g_array_free is provided byt he QEMU program we are being linked into
23    pub(crate) fn g_array_free(array: *mut GArray, free_segment: bool) -> *mut u8;
24}
25
26#[cfg(windows)]
27lazy_static::lazy_static! {
28    static ref G_FREE : libloading::os::windows::Symbol<unsafe extern "C" fn(*mut c_void)> = {
29        let lib =
30            libloading::os::windows::Library::open_already_loaded("libglib-2.0-0.dll")
31                .expect("libglib-2.0-0.dll should already be loaded");
32        // SAFETY
33        // "Users of `Library::get` should specify the correct type of the function loaded".
34        // We are specifying the correct type of g_free above (`void g_free(void*)`)
35        unsafe{lib.get(b"g_free").expect("find g_free")}
36    };
37}
38
39#[cfg(all(
40    windows,
41    not(any(feature = "plugin-api-v0", feature = "plugin-api-v1"))
42))]
43lazy_static::lazy_static! {
44    static ref G_BYTE_ARRAY_NEW: libloading::os::windows::Symbol<unsafe extern "C" fn() -> *mut GByteArray> = {
45        let lib =
46            libloading::os::windows::Library::open_already_loaded("libglib-2.0-0.dll")
47                .expect("libglib-2.0-0.dll should already be loaded");
48        // SAFETY
49        // "Users of `Library::get` should specify the correct type of the function loaded".
50        // We are specifying the correct type of g_free above (`void g_free(void*)`)
51        unsafe{lib.get(b"g_byte_array_new").expect("find g_byte_array_new")}
52    };
53}
54
55#[cfg(all(
56    windows,
57    not(any(feature = "plugin-api-v0", feature = "plugin-api-v1"))
58))]
59lazy_static::lazy_static! {
60    static ref G_BYTE_ARRAY_FREE: libloading::os::windows::Symbol<unsafe extern "C" fn(*mut c_void, bool) -> *mut u8> = {
61        let lib =
62            libloading::os::windows::Library::open_already_loaded("libglib-2.0-0.dll")
63                .expect("libglib-2.0-0.dll should already be loaded");
64        // SAFETY
65        // "Users of `Library::get` should specify the correct type of the function loaded".
66        // We are specifying the correct type of g_free above (`void g_free(void*)`)
67        unsafe{lib.get(b"g_byte_array_free").expect("find g_byte_array_free")}
68    };
69}
70
71#[cfg(all(
72    windows,
73    not(any(feature = "plugin-api-v0", feature = "plugin-api-v1"))
74))]
75lazy_static::lazy_static! {
76    static ref G_ARRAY_FREE: libloading::os::windows::Symbol<unsafe extern "C" fn(*mut c_void, bool) -> *mut u8> = {
77        let lib =
78            libloading::os::windows::Library::open_already_loaded("libglib-2.0-0.dll")
79                .expect("libglib-2.0-0.dll should already be loaded");
80        // SAFETY
81        // "Users of `Library::get` should specify the correct type of the function loaded".
82        // We are specifying the correct type of g_free above (`void g_free(void*)`)
83        unsafe{lib.get(b"g_array_free").expect("find g_array_free")}
84    };
85}
86
87#[cfg(windows)]
88/// Define g_free, because on Windows we cannot delay link it
89///
90/// # Safety
91///
92/// `g_free` must *only* be used to deallocate values allocated with `g_malloc`, regardless of
93/// its documented guarantees about wrapping the system allocator. QEMU plugin APIs which return
94/// such values are documented to do so, and it is safe to call `g_free` on these values
95/// provided they are not used afterward.
96pub(crate) unsafe fn g_free(mem: *mut c_void) {
97    unsafe { G_FREE(mem) }
98}
99
100#[cfg(all(
101    windows,
102    not(any(feature = "plugin-api-v0", feature = "plugin-api-v1"))
103))]
104/// Define g_byte_array_new, because on Windows we cannot delay link it
105///
106/// # Safety
107///
108/// `g_byte_array_new` must be used to allocate a new `GByteArray` which can be used to store
109/// arbitrary data. The returned `GByteArray` must be freed with `g_byte_array_free` when it is
110/// no longer needed.
111pub(crate) unsafe fn g_byte_array_new() -> *mut GByteArray {
112    unsafe { G_BYTE_ARRAY_NEW() }
113}
114
115#[cfg(all(
116    windows,
117    not(any(feature = "plugin-api-v0", feature = "plugin-api-v1"))
118))]
119/// Define g_byte_array_free, because on Windows we cannot delay link it
120///
121/// # Safety
122///
123/// `g_byte_array_free` must be used to free a `GByteArray` allocated with `g_byte_array_new`.
124/// The `free_segment` argument should be `true` if the data stored in the `GByteArray` should
125/// also be freed. If `false`, the data will not be freed, and the caller is responsible for
126/// freeing it with `g_free`.
127pub(crate) unsafe fn g_byte_array_free(array: *mut GByteArray, free_segment: bool) -> *mut u8 {
128    unsafe { G_BYTE_ARRAY_FREE(array as *mut c_void, free_segment) }
129}
130
131#[cfg(all(
132    windows,
133    not(any(feature = "plugin-api-v0", feature = "plugin-api-v1"))
134))]
135/// Define g_array_free, because on Windows we cannot delay link it
136///
137/// # Safety
138///
139/// `g_array_free` must be used to free a `GArray` allocated with `g_array_new`. The `free_segment`
140/// argument should be `true` if the data stored in the `GArray` should also be freed. If `false`,
141/// the data will not be freed, and the caller is responsible for freeing it with `g_free`.
142pub(crate) unsafe fn g_array_free(array: *mut GArray, free_segment: bool) -> *mut u8 {
143    unsafe { G_ARRAY_FREE(array as *mut c_void, free_segment) }
144}