зеркало из https://github.com/microsoft/com-rs.git
Take advantage of InterfacePtr
This commit is contained in:
Родитель
382ab03b7c
Коммит
972d15102d
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче