Take advantage of InterfacePtr

This commit is contained in:
Ryan Levick 2019-09-20 18:54:58 +02:00
Родитель 382ab03b7c
Коммит 972d15102d
5 изменённых файлов: 30 добавлений и 34 удалений

Просмотреть файл

@ -152,9 +152,9 @@ pub fn gen_set_aggregate_fns(aggr_map: &HashMap<Ident, Vec<Ident>>) -> HelperTok
for base in aggr_base_interface_idents {
let set_aggregate_fn_ident = macro_utils::set_aggregate_fn_ident(&base);
fns.push(quote!(
fn #set_aggregate_fn_ident(&mut self, aggr: *mut *const <dyn com::interfaces::iunknown::IUnknown as com::ComInterface>::VTable) {
fn #set_aggregate_fn_ident(&mut self, aggr: com::InterfacePtr<dyn com::interfaces::iunknown::IUnknown>) {
// TODO: What happens if we are overwriting an existing aggregate?
self.#aggr_field_ident = aggr
self.#aggr_field_ident = aggr.as_raw() as *mut *const <dyn com::interfaces::iunknown::IUnknown as com::ComInterface>::VTable;
}
));
}

Просмотреть файл

@ -45,3 +45,12 @@ impl<T: ?Sized + ComInterface> InterfacePtr<T> {
self.ptr.as_ptr()
}
}
impl<T: ComInterface> Clone for InterfacePtr<T> {
fn clone(&self) -> Self {
InterfacePtr {
ptr: self.ptr,
phantom: PhantomData,
}
}
}

Просмотреть файл

@ -1,8 +1,7 @@
use crate::{interfaces::iunknown::IUnknown, ComInterface, IID};
use std::ptr::NonNull;
use crate::{interface_ptr::InterfacePtr, interfaces::iunknown::IUnknown, ComInterface, IID};
use std::marker::PhantomData;
use winapi::ctypes::c_void;
use winapi::shared::winerror::{E_NOINTERFACE, E_POINTER, FAILED};
@ -16,29 +15,15 @@ use winapi::shared::winerror::{E_NOINTERFACE, E_POINTER, FAILED};
///
/// [`InterfacePtr`]: struct.InterfacePtr.html
pub struct InterfaceRc<T: ?Sized + ComInterface> {
ptr: NonNull<c_void>,
ptr: InterfacePtr<T>,
phantom: PhantomData<T>,
}
impl<T: ?Sized + ComInterface> InterfaceRc<T> {
/// Creates a new `InterfaceRc` that comforms to the interface T.
///
/// # Safety
///
/// `ptr` must be a valid interface pointer for interface `T`. An interface
/// pointer as the name suggests points to an interface struct. A valid
/// interface is itself trivial castable to a `*mut T::VTable`. In other words,
/// `ptr` should also be equal to `*mut *mut T::VTable`.
///
/// `ptr` is owned by `InterfaceRc` and thus the `InterfaceRc` is responsible
/// for its destruction.
///
/// # Panics
///
/// Panics if `ptr` is null.
pub unsafe fn new(ptr: *mut c_void) -> InterfaceRc<T> {
pub fn new(ptr: InterfacePtr<T>) -> InterfaceRc<T> {
InterfaceRc {
ptr: NonNull::new(ptr).expect("ptr was null"),
ptr,
phantom: PhantomData,
}
}
@ -46,7 +31,7 @@ impl<T: ?Sized + ComInterface> InterfaceRc<T> {
/// Gets the underlying interface ptr. This ptr is only guarnteed to live for
/// as long as the current `InterfaceRc` is alive.
pub fn as_raw(&self) -> *mut c_void {
self.ptr.as_ptr()
self.ptr.as_raw()
}
/// A safe version of `QueryInterface`. If the backing CoClass implements the
@ -63,7 +48,7 @@ impl<T: ?Sized + ComInterface> InterfaceRc<T> {
return None;
}
assert!(!ppv.is_null(), "The pointer to the interface returned from a successful call to QueryInterface was null");
unsafe { Some(InterfaceRc::new(ppv)) }
Some(InterfaceRc::new(unsafe { InterfacePtr::new(ppv) }))
}
}
@ -71,7 +56,7 @@ impl<T: ComInterface + ?Sized> Drop for InterfaceRc<T> {
fn drop(&mut self) {
unsafe {
self.release();
// self.ptr may be dangling at this point
// self.ptr may contain a dangling pointer at this point
}
}
}
@ -79,7 +64,7 @@ impl<T: ComInterface + ?Sized> Drop for InterfaceRc<T> {
impl<T: ComInterface> Clone for InterfaceRc<T> {
fn clone(&self) -> Self {
let new_ptr = InterfaceRc {
ptr: self.ptr,
ptr: self.ptr.clone(),
phantom: PhantomData,
};
new_ptr.add_ref();

Просмотреть файл

@ -11,7 +11,7 @@ use winapi::{
use crate::{
interfaces::iunknown::{IUnknown, IUnknownVPtr},
ComInterface, InterfaceRc,
ComInterface, InterfacePtr, InterfaceRc,
};
#[com_interface(00000001-0000-0000-c000-000000000046)]
@ -34,6 +34,6 @@ impl InterfaceRc<dyn IClassFactory> {
// TODO: decide what failures are possible
return None;
}
unsafe { Some(InterfaceRc::new(ppv)) }
Some(InterfaceRc::new(unsafe { InterfacePtr::new(ppv) }))
}
}

Просмотреть файл

@ -15,7 +15,7 @@ use winapi::{
use crate::{
interfaces::iclass_factory::{IClassFactory, IID_ICLASS_FACTORY},
CoClass, ComInterface, InterfaceRc,
CoClass, ComInterface, InterfacePtr, InterfaceRc,
};
pub struct ApartmentThreadedRuntime {
@ -55,7 +55,9 @@ impl ApartmentThreadedRuntime {
return Err(hr);
}
unsafe { Ok(InterfaceRc::new(class_factory)) }
Ok(InterfaceRc::new(unsafe {
InterfacePtr::new(class_factory)
}))
}
pub fn create_instance<T: ComInterface + ?Sized>(
@ -64,7 +66,7 @@ impl ApartmentThreadedRuntime {
) -> Result<InterfaceRc<T>, HRESULT> {
unsafe {
Ok(InterfaceRc::new(
self.create_raw_instance::<T>(clsid, std::ptr::null_mut())? as *mut c_void,
self.create_raw_instance::<T>(clsid, std::ptr::null_mut())?,
))
}
}
@ -73,7 +75,7 @@ impl ApartmentThreadedRuntime {
&self,
clsid: &IID,
outer: &mut U,
) -> Result<*mut *const T::VTable, HRESULT> {
) -> Result<InterfacePtr<T>, HRESULT> {
unsafe { self.create_raw_instance::<T>(clsid, outer as *mut U as LPUNKNOWN) }
}
@ -81,7 +83,7 @@ impl ApartmentThreadedRuntime {
&self,
clsid: &IID,
outer: LPUNKNOWN,
) -> Result<*mut *const T::VTable, HRESULT> {
) -> Result<InterfacePtr<T>, HRESULT> {
let mut instance = std::ptr::null_mut::<c_void>();
let hr = CoCreateInstance(
clsid as REFCLSID,
@ -94,7 +96,7 @@ impl ApartmentThreadedRuntime {
return Err(hr);
}
Ok(instance as *mut *const T::VTable)
Ok(InterfacePtr::new(instance))
}
}