start api; start system

master
Avril 4 years ago
parent f6607bdbb0
commit e5e3d0050c
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -59,7 +59,14 @@
- [X] GHOST_TabletData - [X] GHOST_TabletData
- [X] /Constants/ - [X] /Constants/
- [X] =GHOST_TABLET_DATA_NONE= (reimpl. as ~const fn GHOST_TabletData::none()~) - [X] =GHOST_TABLET_DATA_NONE= (reimpl. as ~const fn GHOST_TabletData::none()~)
- [ ] ~GHOST_C-api.h~ - [-] ~GHOST_C-api.h~
- [-] /Functions/
- [X] GHOST_CreateSystem
- [X] GHOST_SystemInitDebug
- [X] GHOST_DisposeSystem
- [ ] GHOST_ShowMessageBox
- [X] /Function pointers/
- [X] GHOST_EventCallbackProcPtr
*** Native Rust API *** Native Rust API
Rust native APIs are provided for things where the C API bindings are cumbersome or unsafe. Rust native APIs are provided for things where the C API bindings are cumbersome or unsafe.
@ -73,7 +80,11 @@
- [X] [[Handles]]: ~handle.rs~ - [X] [[Handles]]: ~handle.rs~
- [X] [[Error handling]]: ~error.rs~ - [X] [[Error handling]]: ~error.rs~
- [ ] Events: ~event.rs~ - [ ] Events: ~event.rs~
- [ ] Aliases - [ ] Modules
- [ ] [[System]] ~system.rs~
**** TODO System
Provides a Rust wrapper around the GHOST system.
**** Handles **** Handles
Handles keep the C ABI, but are re-wrtten with traits to be more idiomatic. Handles keep the C ABI, but are re-wrtten with traits to be more idiomatic.

@ -0,0 +1,18 @@
//! C API functions and interop
use super::{
*,
handle::*,
c::*,
};
use libc::{
c_int,
};
use std::{
ptr::NonNull,
};
extern "C" {
pub fn GHOST_CreateSystem() -> GHOST_SystemHandle;
pub fn GHOST_SystemInitDebug(_: GHOST_SystemHandle, _: c_int);
pub fn GHOST_DisposeSystem(_: GHOST_SystemHandle) -> GHOST_TSuccess;
}

@ -27,6 +27,11 @@ pub use super::{
GHOST_DialogOptions, GHOST_DialogOptions,
GHOST_TabletData, GHOST_TabletData,
}, },
api::{
GHOST_CreateSystem,
GHOST_DisposeSystem,
GHOST_SystemInitDebug,
},
handle::{ handle::{
GHOST_SystemHandle, GHOST_SystemHandle,
GHOST_TimerTaskHandle, GHOST_TimerTaskHandle,

@ -73,7 +73,7 @@ pub type GhostResult<T = ()> = Result<T, GhostError>;
/// Error type for failed GHOST calls. /// Error type for failed GHOST calls.
/// As of yet it doesn't contain any information and is just an opaque zero-sized structure. /// As of yet it doesn't contain any information and is just an opaque zero-sized structure.
#[derive(Debug)] #[derive(Debug)]
pub struct GhostError(()); pub struct GhostError(pub(crate) ());
impl error::Error for GhostError{} impl error::Error for GhostError{}
impl fmt::Display for GhostError impl fmt::Display for GhostError
{ {

@ -5,6 +5,23 @@ use super::*;
pub use types::{Handle,GhostHandle}; pub use types::{Handle,GhostHandle};
pub(crate) trait AsHandle<T: GhostHandle>
{
fn as_handle(&mut self) -> &mut Handle<T>;
#[inline] fn as_raw(&mut self) -> *mut Handle<T>
{
self.as_handle() as *mut Handle<T>
}
}
impl<T: GhostHandle> AsHandle<T> for Handle<T>
{
#[inline] fn as_handle(&mut self) -> &mut Handle<T>
{
self
}
}
#[cfg(not(nightly))] enum HandleInner{} #[cfg(not(nightly))] enum HandleInner{}
macro_rules! handle { macro_rules! handle {
@ -25,3 +42,10 @@ handle!(GHOST_RectangleHandle, Rectangle);
handle!(GHOST_EventConsumerHandle, EventConsumer); handle!(GHOST_EventConsumerHandle, EventConsumer);
handle!(GHOST_ContextHandle, Context); handle!(GHOST_ContextHandle, Context);
handle!(GHOST_XrContextHandle, XrContextHandle); handle!(GHOST_XrContextHandle, XrContextHandle);
// This is very unsafe.
/*#[inline] pub(crate) unsafe fn coerce<'a, T>(from: *mut Handle<T>) -> &'a mut Handle<T>
where T: GhostHandle
{
std::mem::transmute::<*mut _, &'a mut _>(from) //this is needed because we can't safely dereference `Handle<T>`.
}*/

@ -29,6 +29,48 @@ pub mod handle;
pub mod event; pub mod event;
pub mod types; pub mod types;
pub mod error; pub mod error;
pub mod api;
macro_rules! from_null {
($ptr:expr) => {
{
let ptr = $ptr;
if ptr.is_null() {
return Err($crate::error::GhostError(()))?;
} else {
ptr
}
}
};
(return $ptr:expr) => {
{
let ptr = $ptr;
if ptr.is_null() {
Err($crate::error::GhostError(()))
} else {
Ok(ptr)
}
}
}
}
macro_rules! debug {
($debug:expr; $prod:expr) => {
{
#[cfg(debug_assertions)] $debug;
#[cfg(not(debug_assertions))] $prod;
}
};
($debug:expr) => {
{
#[cfg(debug_assertions)] $debug
}
};
}
pub mod system;
pub mod c; pub mod c;

@ -0,0 +1,84 @@
//! Container for `GHOST_SystemHandle`
use super::*;
use handle::*;
use std::{
ptr::NonNull,
ops::Drop,
};
/// Represents the active GHOST system.
///
/// This is global state, and only one can exist at once time.
/// # Usage
/// Create with the `create()` function. When the instance is dropped, the system is attempted to be disposed of.
/// This is not an associated function, to specify that creating the system is a global event, not an associated one.
///
/// # Panics
/// On debug builds a failed dispose on drop will panic. You can call `try_drop()` to attempt the dispose manually.
#[derive(Debug)]
pub struct System(NonNull<Handle<handle::System>>);
impl System
{
pub(crate) unsafe fn new_unchecked(from: *mut Handle<handle::System>) -> Self
{
Self(NonNull::new_unchecked(from))
}
/// Specifies whether debug messages are to be enabled for the specific system handle.
pub fn debug_messages(&mut self, enable: bool)
{
unsafe {
api::GHOST_SystemInitDebug(self.as_raw(), enable as libc::c_int);
}
}
/// Try to dispose the system now, returning the result.
pub fn try_drop(self) -> error::GhostResult
{
let res = unsafe {
api::GHOST_DisposeSystem(self.0.as_ptr())
};
std::mem::forget(self);
res.into()
}
#[inline] pub fn inner_handle(&mut self) -> GHOST_SystemHandle
{
self.0.as_ptr()
}
}
impl handle::AsHandle<handle::System> for System
{
#[inline] fn as_handle(&mut self) -> &mut Handle<handle::System> {
unsafe{self.0.as_mut()}
}
#[inline] fn as_raw(&mut self) -> *mut Handle<handle::System> {
self.inner_handle()
}
}
impl Drop for System
{
fn drop(&mut self)
{
unsafe {
let ptr = self.0.as_ptr();
debug!(api::GHOST_DisposeSystem(ptr).into_result().expect("Failed to dispose system");
{let _ = api::GHOST_DisposeSystem(ptr);});
}
}
}
/// Create the one and only system.
///
/// You must not call `create()` again as long as the system lives. After dropping the system it may or may not be safe to call this again.
pub fn create() -> error::GhostResult<System>
{
unsafe {
let ptr = from_null!(api::GHOST_CreateSystem());
Ok(System::new_unchecked(ptr))
}
}

@ -168,6 +168,9 @@ enum_flags!(GHOST_DialogOptions
DialogError = 1<<1, DialogError = 1<<1,
}); });
/// Value returned by some GHOST functions to indicate a success or failure.
///
/// For mapping this behaviour onto Rust, see ['GhostResult`](./error/type.GhostResult.html).
#[repr(C)] #[repr(C)]
#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub enum GHOST_TSuccess pub enum GHOST_TSuccess
@ -375,3 +378,10 @@ pub enum GHOST_TEventType {
NumEventTypes NumEventTypes
} }
/**
* Definition of a callback routine that receives events.
* * The event received.
* * The callback's user data, supplied to GHOST_CreateSystem.
*/
pub type GHOST_EventCallbackProcPtr = Option<fn(handle::GHOST_EventHandle, GHOST_TUserDataPtr) -> libc::c_int>;

Loading…
Cancel
Save