feat: finish cdylib ffi and improve ffi C header
This commit is contained in:
@@ -5,7 +5,7 @@
|
|||||||
# This module requires the user to set wfassoc_ROOT to the installation
|
# This module requires the user to set wfassoc_ROOT to the installation
|
||||||
# directory of wfassoc. The directory structure under wfassoc_ROOT must be:
|
# directory of wfassoc. The directory structure under wfassoc_ROOT must be:
|
||||||
# bin/ - contains wfassoc_cdylib.dll
|
# bin/ - contains wfassoc_cdylib.dll
|
||||||
# include/ - contains wfassoc.h and wfassoc.hpp
|
# include/ - contains wfassoc.h
|
||||||
# lib/ - contains wfassoc_cdylib.dll.lib (import library)
|
# lib/ - contains wfassoc_cdylib.dll.lib (import library)
|
||||||
#
|
#
|
||||||
# This module defines the following variables:
|
# This module defines the following variables:
|
||||||
@@ -36,7 +36,7 @@ set(wfassoc_LIB_DIR ${wfassoc_ROOT}/lib)
|
|||||||
set(wfassoc_BIN_DIR ${wfassoc_ROOT}/bin)
|
set(wfassoc_BIN_DIR ${wfassoc_ROOT}/bin)
|
||||||
|
|
||||||
# Find header files
|
# Find header files
|
||||||
if(EXISTS ${wfassoc_INCLUDE_DIR}/wfassoc.h AND EXISTS ${wfassoc_INCLUDE_DIR}/wfassoc.hpp)
|
if(EXISTS ${wfassoc_INCLUDE_DIR}/wfassoc.h)
|
||||||
set(wfassoc_INCLUDE_DIRS ${wfassoc_INCLUDE_DIR})
|
set(wfassoc_INCLUDE_DIRS ${wfassoc_INCLUDE_DIR})
|
||||||
else()
|
else()
|
||||||
message(SEND_ERROR "Missing wfassoc header files in ${wfassoc_INCLUDE_DIR}")
|
message(SEND_ERROR "Missing wfassoc header files in ${wfassoc_INCLUDE_DIR}")
|
||||||
|
|||||||
@@ -2,28 +2,50 @@
|
|||||||
#ifndef __WFASSOC_H__
|
#ifndef __WFASSOC_H__
|
||||||
#define __WFASSOC_H__
|
#define __WFASSOC_H__
|
||||||
|
|
||||||
#include <stdarg.h>
|
#ifdef __cplusplus
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#else // __cplusplus
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
|
||||||
typedef const char *CStyleString;
|
|
||||||
|
|
||||||
typedef uint64_t Token;
|
|
||||||
|
|
||||||
typedef uint32_t Scope;
|
|
||||||
#define SCOPE_USER 0u
|
|
||||||
#define SCOPE_SYSTEM 1u
|
|
||||||
|
|
||||||
typedef uint32_t View;
|
|
||||||
#define VIEW_USER 0u
|
|
||||||
#define VIEW_SYSTEM 1u
|
|
||||||
#define VIEW_HYBRID 2u
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
using CStyleString = const char*;
|
||||||
|
using Token = uint64_t;
|
||||||
|
using HICON = void*;
|
||||||
|
#else // __cplusplus
|
||||||
|
typedef const char *CStyleString;
|
||||||
|
typedef uint64_t Token;
|
||||||
|
typedef void *HICON;
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
enum class Scope : uint32_t {
|
||||||
|
User = 0u,
|
||||||
|
System = 1u
|
||||||
|
};
|
||||||
|
enum class View : uint32_t {
|
||||||
|
User = 0u,
|
||||||
|
System = 1u,
|
||||||
|
Hybrid = 2u
|
||||||
|
};
|
||||||
|
#else // __cplusplus
|
||||||
|
typedef uint32_t Scope;
|
||||||
|
static const Scope SCOPE_USER = 0u;
|
||||||
|
static const Scope SCOPE_SYSTEM = 1u;
|
||||||
|
typedef uint32_t View;
|
||||||
|
static const View VIEW_USER = 0u;
|
||||||
|
static const View VIEW_SYSTEM = 1u;
|
||||||
|
static const View VIEW_HYBRID = 2u;
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
namespace wfassoc {
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
||||||
@@ -35,6 +57,8 @@ CStyleString WFGetLastError(void);
|
|||||||
|
|
||||||
bool WFHasPrivilege(void);
|
bool WFHasPrivilege(void);
|
||||||
|
|
||||||
|
Token WFInvalidToken(void);
|
||||||
|
|
||||||
bool WFSchemaCreate(Token *out_schema);
|
bool WFSchemaCreate(Token *out_schema);
|
||||||
|
|
||||||
bool WFSchemaDestroy(Token in_schema);
|
bool WFSchemaDestroy(Token in_schema);
|
||||||
@@ -67,18 +91,27 @@ bool WFProgramCreate(Token in_schema, Token *out_program);
|
|||||||
|
|
||||||
bool WFProgramDestroy(Token in_program);
|
bool WFProgramDestroy(Token in_program);
|
||||||
|
|
||||||
bool WFProgramRegister(Token in_program, uint32_t in_scope);
|
bool WFProgramRegister(Token in_program, Scope in_scope);
|
||||||
|
|
||||||
bool WFProgramUnregister(Token in_program, uint32_t in_scope);
|
bool WFProgramUnregister(Token in_program, Scope in_scope);
|
||||||
|
|
||||||
bool WFProgramIsRegistered(Token in_program, uint32_t in_scope, bool *out_is_registered);
|
bool WFProgramIsRegistered(Token in_program, Scope in_scope, bool *out_is_registered);
|
||||||
|
|
||||||
bool WFProgramLinkExt(Token in_program, uint32_t in_scope, size_t in_index);
|
bool WFProgramLinkExt(Token in_program, Scope in_scope, size_t in_index);
|
||||||
|
|
||||||
bool WFProgramUnlinkExt(Token in_program, uint32_t in_scope, size_t in_index);
|
bool WFProgramUnlinkExt(Token in_program, Scope in_scope, size_t in_index);
|
||||||
|
|
||||||
|
bool WFProgramQueryExt(Token in_program, View in_view, size_t in_index, Token *out_ext_status);
|
||||||
|
|
||||||
|
bool WFExtStatusDestroy(Token in_ext_status);
|
||||||
|
|
||||||
|
bool WFExtStatuGetName(Token in_ext_status, CStyleString *out_name);
|
||||||
|
|
||||||
|
bool WFExtStatuGetIcon(Token in_ext_status, HICON *out_icon);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
} // namespace wfassoc
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
|
|
||||||
#endif // __WFASSOC_H__
|
#endif // __WFASSOC_H__
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
enum class Scope : uint32_t {
|
|
||||||
User = 0u,
|
|
||||||
System = 1u
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class View : uint32_t {
|
|
||||||
User = 0u,
|
|
||||||
System = 1u,
|
|
||||||
Hybrid = 2u
|
|
||||||
};
|
|
||||||
|
|
||||||
using Token = uint64_t;
|
|
||||||
|
|
||||||
using CStyleString = const char*;
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
bool WFStartup(void);
|
|
||||||
|
|
||||||
bool WFShutdown(void);
|
|
||||||
|
|
||||||
CStyleString WFGetLastError(void);
|
|
||||||
|
|
||||||
bool WFHasPrivilege(void);
|
|
||||||
|
|
||||||
bool WFSchemaCreate(Token *out_schema);
|
|
||||||
|
|
||||||
bool WFSchemaDestroy(Token in_schema);
|
|
||||||
|
|
||||||
bool WFSchemaSetIdentifier(Token in_schema, CStyleString in_value);
|
|
||||||
|
|
||||||
bool WFSchemaSetPath(Token in_schema, CStyleString in_value);
|
|
||||||
|
|
||||||
bool WFSchemaSetClsid(Token in_schema, CStyleString in_value);
|
|
||||||
|
|
||||||
bool WFSchemaSetName(Token in_schema, CStyleString in_value);
|
|
||||||
|
|
||||||
bool WFSchemaSetIcon(Token in_schema, CStyleString in_value);
|
|
||||||
|
|
||||||
bool WFSchemaSetBehavior(Token in_schema, CStyleString in_value);
|
|
||||||
|
|
||||||
bool WFSchemaAddStr(Token in_schema, CStyleString in_name, CStyleString in_value);
|
|
||||||
|
|
||||||
bool WFSchemaAddIcon(Token in_schema, CStyleString in_name, CStyleString in_value);
|
|
||||||
|
|
||||||
bool WFSchemaAddBehavior(Token in_schema, CStyleString in_name, CStyleString in_value);
|
|
||||||
|
|
||||||
bool WFSchemaAddExt(Token in_schema,
|
|
||||||
CStyleString in_ext,
|
|
||||||
CStyleString in_ext_name,
|
|
||||||
CStyleString in_ext_icon,
|
|
||||||
CStyleString in_ext_behavior);
|
|
||||||
|
|
||||||
bool WFProgramCreate(Token in_schema, Token *out_program);
|
|
||||||
|
|
||||||
bool WFProgramDestroy(Token in_program);
|
|
||||||
|
|
||||||
bool WFProgramRegister(Token in_program, uint32_t in_scope);
|
|
||||||
|
|
||||||
bool WFProgramUnregister(Token in_program, uint32_t in_scope);
|
|
||||||
|
|
||||||
bool WFProgramIsRegistered(Token in_program, uint32_t in_scope, bool *out_is_registered);
|
|
||||||
|
|
||||||
bool WFProgramLinkExt(Token in_program, uint32_t in_scope, size_t in_index);
|
|
||||||
|
|
||||||
bool WFProgramUnlinkExt(Token in_program, uint32_t in_scope, size_t in_index);
|
|
||||||
|
|
||||||
}
|
|
||||||
66
wfassoc-cdylib/src/ffi_types.rs
Normal file
66
wfassoc-cdylib/src/ffi_types.rs
Normal 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
|
||||||
@@ -1,16 +1,13 @@
|
|||||||
mod cstr_ffi;
|
mod cstr_ffi;
|
||||||
mod last_error;
|
mod last_error;
|
||||||
mod object_pool;
|
mod object_pool;
|
||||||
|
mod ffi_types;
|
||||||
|
|
||||||
use num_enum::TryFromPrimitive;
|
|
||||||
use object_pool::ObjectPool;
|
use object_pool::ObjectPool;
|
||||||
use std::sync::{LazyLock, RwLock};
|
use std::sync::{LazyLock, RwLock};
|
||||||
use thiserror::Error as TeError;
|
use thiserror::Error as TeError;
|
||||||
use wfassoc::highlevel::{Program, Schema};
|
use wfassoc::highlevel::{Program, Schema};
|
||||||
|
|
||||||
pub use cstr_ffi::CStyleString;
|
|
||||||
pub use object_pool::Token;
|
|
||||||
|
|
||||||
// region: Error
|
// region: Error
|
||||||
|
|
||||||
/// Error occurs in this crate.
|
/// Error occurs in this crate.
|
||||||
@@ -198,39 +195,9 @@ static EXT_STATUE_POOL: LazyLock<RwLock<ObjectPool<wfassoc::highlevel::ProgramEx
|
|||||||
|
|
||||||
// region: Exposed Types
|
// region: Exposed Types
|
||||||
|
|
||||||
#[repr(u32)]
|
pub use cstr_ffi::CStyleString;
|
||||||
#[derive(Debug, Copy, Clone, TryFromPrimitive)]
|
pub use object_pool::Token;
|
||||||
pub enum Scope {
|
pub use ffi_types::{HICON, Scope, View};
|
||||||
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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
@@ -273,6 +240,11 @@ pub extern "C" fn WFHasPrivilege() -> bool {
|
|||||||
wfassoc::win32::utilities::has_privilege()
|
wfassoc::win32::utilities::has_privilege()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "C" fn WFInvalidToken() -> Token {
|
||||||
|
object_pool::invalid_token()
|
||||||
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
// region: Schema
|
// region: Schema
|
||||||
@@ -581,11 +553,16 @@ pub extern "C" fn WFProgramQueryExt(
|
|||||||
let pool = pull_reader!(PROGRAM_POOL)?;
|
let pool = pull_reader!(PROGRAM_POOL)?;
|
||||||
let program = pool.get(in_program)?;
|
let program = pool.get(in_program)?;
|
||||||
let view = resolve_enum!(View, in_view)?;
|
let view = resolve_enum!(View, in_view)?;
|
||||||
|
|
||||||
let ext_status = program.query_ext(view.into(), in_index)?;
|
let ext_status = program.query_ext(view.into(), in_index)?;
|
||||||
todo!();
|
let token = match ext_status {
|
||||||
let mut pool = pull_writer!(EXT_STATUE_POOL)?;
|
Some(ext_status) => {
|
||||||
Ok(pool.allocate(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)]
|
#[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) {
|
cffi_wrapper!(|in_ext_status: Token| -> (out_name: CStyleString) {
|
||||||
let pool = pull_reader!(EXT_STATUE_POOL)?;
|
let pool = pull_reader!(EXT_STATUE_POOL)?;
|
||||||
let ext_status = pool.get(in_ext_status)?;
|
let ext_status = pool.get(in_ext_status)?;
|
||||||
|
|
||||||
cstr_ffi::set_ffi_string(ext_status.get_name())?;
|
cstr_ffi::set_ffi_string(ext_status.get_name())?;
|
||||||
Ok(cstr_ffi::get_ffi_string())
|
Ok(cstr_ffi::get_ffi_string())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[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) {
|
cffi_wrapper!(|in_ext_status: Token| -> (out_icon: HICON) {
|
||||||
let pool = pull_reader!(EXT_STATUE_POOL)?;
|
let pool = pull_reader!(EXT_STATUE_POOL)?;
|
||||||
let ext_status = pool.get(in_ext_status)?;
|
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)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,14 @@ pub enum Error {
|
|||||||
/// The token for fetching object in [ObjectPool].
|
/// The token for fetching object in [ObjectPool].
|
||||||
pub type Token = u64;
|
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.
|
/// A pool for managing objects with unique tokens.
|
||||||
///
|
///
|
||||||
/// It is highly suggested to use this pool with [std::sync::RwLock] guard.
|
/// It is highly suggested to use this pool with [std::sync::RwLock] guard.
|
||||||
|
|||||||
Reference in New Issue
Block a user