1
0

feat: finish cdylib ffi and improve ffi C header

This commit is contained in:
2026-05-18 13:33:57 +08:00
parent f1a7cb89e5
commit 91c7fdda70
6 changed files with 164 additions and 143 deletions

View File

@@ -0,0 +1,66 @@
//! The module including all FFI types used by this crate.
use std::ffi::c_void;
use num_enum::TryFromPrimitive;
// region: HICON
/// The type representing Win32 HICON handle.
///
/// In theory, we can fetch HICON type from "windows_sys" crate.
/// However, I don't want to add it as this crate's dependency,
/// because I don't use anything within it except this type.
/// So I check Microsoft document, re-define it in there for this crate.
/// Reference: https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types
pub type HICON = *mut c_void;
/// The invalid value of Win32 HICON handle.
///
/// The same reason like [HICON] to re-define it in there.
pub const INVALID_ICON: HICON = std::ptr::null_mut();
// endregion
// region: Scope
/// The FFI wrapper for [wfassoc::Scope].
#[repr(u32)]
#[derive(Debug, Copy, Clone, TryFromPrimitive)]
pub enum Scope {
User = 0,
System = 1,
}
impl From<Scope> for wfassoc::Scope {
fn from(value: Scope) -> Self {
match value {
Scope::User => wfassoc::Scope::User,
Scope::System => wfassoc::Scope::System,
}
}
}
// endregion
// region: View
/// The FFI wrapper for [wfassoc::View].
#[repr(u32)]
#[derive(Debug, Copy, Clone, TryFromPrimitive)]
pub enum View {
User = 0,
System = 1,
Hybrid = 2,
}
impl From<View> for wfassoc::View {
fn from(value: View) -> Self {
match value {
View::User => wfassoc::View::User,
View::System => wfassoc::View::System,
View::Hybrid => wfassoc::View::Hybrid,
}
}
}
// endregion

View File

@@ -1,16 +1,13 @@
mod cstr_ffi;
mod last_error;
mod object_pool;
mod ffi_types;
use num_enum::TryFromPrimitive;
use object_pool::ObjectPool;
use std::sync::{LazyLock, RwLock};
use thiserror::Error as TeError;
use wfassoc::highlevel::{Program, Schema};
pub use cstr_ffi::CStyleString;
pub use object_pool::Token;
// region: Error
/// Error occurs in this crate.
@@ -198,39 +195,9 @@ static EXT_STATUE_POOL: LazyLock<RwLock<ObjectPool<wfassoc::highlevel::ProgramEx
// region: Exposed Types
#[repr(u32)]
#[derive(Debug, Copy, Clone, TryFromPrimitive)]
pub enum Scope {
User = 0,
System = 1,
}
impl From<Scope> for wfassoc::Scope {
fn from(value: Scope) -> Self {
match value {
Scope::User => wfassoc::Scope::User,
Scope::System => wfassoc::Scope::System,
}
}
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, TryFromPrimitive)]
pub enum View {
User = 0,
System = 1,
Hybrid = 2,
}
impl From<View> for wfassoc::View {
fn from(value: View) -> Self {
match value {
View::User => wfassoc::View::User,
View::System => wfassoc::View::System,
View::Hybrid => wfassoc::View::Hybrid,
}
}
}
pub use cstr_ffi::CStyleString;
pub use object_pool::Token;
pub use ffi_types::{HICON, Scope, View};
// endregion
@@ -273,6 +240,11 @@ pub extern "C" fn WFHasPrivilege() -> bool {
wfassoc::win32::utilities::has_privilege()
}
#[unsafe(no_mangle)]
pub extern "C" fn WFInvalidToken() -> Token {
object_pool::invalid_token()
}
// endregion
// region: Schema
@@ -581,11 +553,16 @@ pub extern "C" fn WFProgramQueryExt(
let pool = pull_reader!(PROGRAM_POOL)?;
let program = pool.get(in_program)?;
let view = resolve_enum!(View, in_view)?;
let ext_status = program.query_ext(view.into(), in_index)?;
todo!();
let mut pool = pull_writer!(EXT_STATUE_POOL)?;
Ok(pool.allocate(ext_status)?)
let token = match ext_status {
Some(ext_status) => {
let mut pool = pull_writer!(EXT_STATUE_POOL)?;
pool.allocate(ext_status)?
},
None => object_pool::invalid_token(),
};
Ok(token)
})
}
@@ -600,22 +577,33 @@ pub extern "C" fn WFExtStatusDestroy(in_ext_status: in_param_ty!(Token)) -> bool
}
#[unsafe(no_mangle)]
pub extern "C" fn WFExtStatuGetName(in_ext_status: in_param_ty!(Token), out_name: out_param_ty!(CStyleString)) -> bool {
pub extern "C" fn WFExtStatuGetName(
in_ext_status: in_param_ty!(Token),
out_name: out_param_ty!(CStyleString),
) -> bool {
cffi_wrapper!(|in_ext_status: Token| -> (out_name: CStyleString) {
let pool = pull_reader!(EXT_STATUE_POOL)?;
let ext_status = pool.get(in_ext_status)?;
cstr_ffi::set_ffi_string(ext_status.get_name())?;
Ok(cstr_ffi::get_ffi_string())
})
}
#[unsafe(no_mangle)]
pub extern "C" fn WFExtStatuGetIcon(in_ext_status: in_param_ty!(Token), out_icon: out_param_ty!(HICON)) -> bool {
pub extern "C" fn WFExtStatuGetIcon(
in_ext_status: in_param_ty!(Token),
out_icon: out_param_ty!(HICON),
) -> bool {
cffi_wrapper!(|in_ext_status: Token| -> (out_icon: HICON) {
let pool = pull_reader!(EXT_STATUE_POOL)?;
let ext_status = pool.get(in_ext_status)?;
Ok(ext_status.get_icon())
let icon = match ext_status.get_icon() {
Some(icon) => icon.get_icon(),
None => ffi_types::INVALID_ICON,
};
Ok(icon)
})
}

View File

@@ -17,6 +17,14 @@ pub enum Error {
/// The token for fetching object in [ObjectPool].
pub type Token = u64;
/// Get the invalid token.
///
/// Invalid token is always invalid for fetching object in pool,
/// And can be useful in FFI scenario.
pub fn invalid_token() -> Token {
DefaultKey::null().data().as_ffi()
}
/// A pool for managing objects with unique tokens.
///
/// It is highly suggested to use this pool with [std::sync::RwLock] guard.