-
-
Notifications
You must be signed in to change notification settings - Fork 392
Pointers for using COM #491
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
I will look into adding an example of this for winapi 0.3 |
Thanks! I was just working with the stable. From what I see in #316, it looks like structuring is one of the issues that it's aims to solve there. That was the primary source of my confusion - having to do It just feels like it's all over the place on the stable (which perhaps, would be okay if RLS/auto-complete provided a hand - but pragmatically, I would presume it's going to be a while before macros are resolved by RLS to a reliable extent) - So, I feel strong and documented conventions are the key to making this more usable. Looking forward to some form of documentation for the COM apis. |
Generally if you want to know where a given symbol is defined in winapi 0.2 and it's sys crates, you'd just use the search bar on https://retep998.github.io/doc/winapi/index.html For winapi 0.3 everything is simply in the module directly corresponding to the header it is from. For winapi 0.3 you can get the IID of any interface through the |
I don't know if this is helpful but this is from my first commit to my sapi project using winapi 0.2 extern crate winapi;
extern crate ole32;
use std::mem;
use std::ptr;
use std::ffi::OsStr;
use std::os::windows::ffi::OsStrExt;
#[inline]
fn failed(hr: winapi::HRESULT) -> bool {
hr < 0
}
#[inline]
fn succeeded(hr: winapi::HRESULT) -> bool {
!failed(hr)
}
pub trait ToWide {
fn to_wide(&self) -> Vec<u16>;
fn to_wide_null(&self) -> Vec<u16>;
}
impl<T> ToWide for T where T: AsRef<OsStr> {
fn to_wide(&self) -> Vec<u16> {
self.as_ref().encode_wide().collect()
}
fn to_wide_null(&self) -> Vec<u16> {
self.as_ref().encode_wide().chain(Some(0)).collect()
}
}
struct Com {
hr: winapi::HRESULT,
}
impl Com {
fn new() -> Com {
println!("new for Con");
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms678543(v=vs.85).aspx
let hr = unsafe {ole32::CoInitialize(ptr::null_mut())};
if failed(hr) {
panic!("failed for Con");
}
Com {hr: hr}
}
}
impl Drop for Com {
fn drop(&mut self) {
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms688715(v=vs.85).aspx
if self.hr != winapi::RPC_E_CHANGED_MODE {
unsafe {
ole32::CoUninitialize();
}
}
println!("drop for Con");
}
}
struct SpVoice<'a> {
// https://msdn.microsoft.com/en-us/library/ms723602(VS.85).aspx
voice: &'a mut winapi::ISpVoice,
}
impl<'a> SpVoice<'a> {
fn new() -> SpVoice<'a> {
println!("new for SpVoice");
let mut hr;
let mut voice: *mut winapi::ISpVoice = ptr::null_mut();
let sp_voice = "SAPI.SpVoice".to_wide_null();
unsafe {
let mut clsid_spvoice: winapi::CLSID = mem::uninitialized();
hr = ole32::CLSIDFromProgID(&sp_voice[0], &mut clsid_spvoice);
if failed(hr) {
panic!("failed for SpVoice at CLSIDFromProgID");
}
hr = ole32::CoCreateInstance(
&clsid_spvoice,
ptr::null_mut(),
winapi::CLSCTX_ALL,
&winapi::UuidOfISpVoice,
&mut voice as *mut *mut winapi::ISpVoice as *mut *mut winapi::c_void
);
if failed(hr) {
panic!("failed for SpVoice at CoCreateInstance");
}
SpVoice {
voice: &mut *voice,
}
}
}
fn speak (&mut self, string: &str) {
unsafe {
println!("befor speak");
self.voice.Speak(string.to_wide_null().as_ptr(), 19, ptr::null_mut());
println!("after speak");
}
}
fn wait (&mut self) {
unsafe {
self.voice.WaitUntilDone(winapi::INFINITE);
}
}
fn speak_wait (&mut self, string: &str) {
self.speak(string);
self.wait();
}
}
impl<'a> Drop for SpVoice<'a> {
fn drop(&mut self) {
unsafe {
self.voice.Release();
}
println!("drop for SpVoice");
}
}
fn main() {
let com = Com::new();
let mut voice = SpVoice::new();
voice.speak_wait("Hello, world!");
voice.speak_wait("Hello, you!");
voice.speak_wait("Hello, me!");
} |
@Eh2406 - Thank you! I believe this is going to be very helpful. This is rather a nice abstraction. I had written something very similar in the end, though I ended up implementing the SpVoice's VTable manually, since macros don't expand on Racer or RLS - Guess I'm addicted to auto-complete, and the future looks even bleaker with feature gates in 0.3 :/ I guess the last two comments address the issue for 0.2, while 0.3, I suppose this is resolved naturally, since it just follows the C headers. Closing :) |
Hi,
Fantastic efforts on putting this together. As I understand, from briefly glancing over the code, there are a lot of macros that help in using COM interfaces. It seems like these interfaces are built into structures with the interface methods as Traits, conforming to the COM ABI. That looks great. And there seems to be UUIDs defined for some.
I was wondering though, if you could perhaps, write a small section on how you had intended this to be used? I was trying to use the SAPI, but I was bit confused, starting with not being able to find where the UUIDs were defined, and so, I ended up pretty much manually implementing what I needed. But it looks redundant since I could clearly see a lot of the interfaces in the code. Little pointers as example would go a long way in helping what's the structure with which you had designed it, so it's helpful to people who also implement this and can contribute efforts back, for the missing components from winapi-rs, like for example the structure where, the CLSID, and the interface IDs are defined, and where exactly the structures go. I see some to be directly in the
winapi-rs
crate (sapi) for example. But for some, I see only structs and constants in it, and the functions in dedicated crates.Let's take for instance, a simple example straight out of MSDN:
Would be great if you could convert this using winapi-rs. :)
The text was updated successfully, but these errors were encountered: