functionalscript 0.0.411 → 0.0.414
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.lock +2 -9
- package/Cargo.toml +1 -2
- package/com/rust/{com → nanocom}/Cargo.lock +0 -0
- package/com/rust/nanocom/Cargo.toml +15 -0
- package/com/rust/nanocom/README.md +3 -0
- package/com/rust/{com → nanocom}/src/class.rs +2 -2
- package/com/rust/{com → nanocom}/src/cobject.rs +5 -8
- package/com/rust/{com → nanocom}/src/guid.rs +0 -0
- package/com/rust/{com → nanocom}/src/hresult.rs +0 -0
- package/com/rust/nanocom/src/interface.rs +9 -0
- package/com/rust/{com/src/iunknownvmt.rs → nanocom/src/iunknown.rs} +3 -3
- package/com/rust/{com → nanocom}/src/lib.rs +2 -3
- package/com/rust/{com → nanocom}/src/object.rs +6 -9
- package/com/rust/{com → nanocom}/src/ref.rs +3 -3
- package/com/rust/nanocom/src/vmt.rs +7 -0
- package/com/rust/nanocom/tests/it.rs +188 -0
- package/package.json +1 -1
- package/com/rust/com/Cargo.toml +0 -8
- package/com/rust/com/rstest/Cargo.lock +0 -14
- package/com/rust/com/rstest/Cargo.toml +0 -9
- package/com/rust/com/rstest/src/lib.rs +0 -109
- package/com/rust/com/src/interface.rs +0 -5
- package/com/rust/com/src/iunknown.rs +0 -7
- package/com/rust/com/src/vmt.rs +0 -7
package/Cargo.lock
CHANGED
package/Cargo.toml
CHANGED
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "nanocom"
|
|
3
|
+
version = "0.1.2"
|
|
4
|
+
edition = "2021"
|
|
5
|
+
description = "Nano-COM, extremly small subset of cross-platform COM"
|
|
6
|
+
authors = ["NatFoam"]
|
|
7
|
+
license = "MIT"
|
|
8
|
+
homepage = "https://github.com/functionalscript/functionalscript/tree/main/com/rust/nanocom"
|
|
9
|
+
repository = "https://github.com/functionalscript/functionalscript"
|
|
10
|
+
keywords = ["com", "xpcom", "abi"]
|
|
11
|
+
categories = ["development-tools::ffi", "external-ffi-bindings", "api-bindings"]
|
|
12
|
+
|
|
13
|
+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
14
|
+
|
|
15
|
+
[dependencies]
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
use crate::{
|
|
1
|
+
use crate::{iunknown::IUnknown, CObject, Interface, Object, Ref, Vmt};
|
|
2
2
|
|
|
3
3
|
pub trait Class: Sized {
|
|
4
4
|
type Interface: Interface;
|
|
5
5
|
fn static_vmt() -> &'static Vmt<Self::Interface>;
|
|
6
|
-
const IUNKNOWN:
|
|
6
|
+
const IUNKNOWN: IUnknown<Self::Interface> = CObject::<Self>::IUNKNOWN;
|
|
7
7
|
fn cobject_new(self) -> Ref<Self::Interface> {
|
|
8
8
|
CObject::new(self)
|
|
9
9
|
}
|
|
@@ -3,10 +3,7 @@ use std::{
|
|
|
3
3
|
sync::atomic::{AtomicU32, Ordering},
|
|
4
4
|
};
|
|
5
5
|
|
|
6
|
-
use crate::{
|
|
7
|
-
hresult::HRESULT, iunknown::IUnknown, iunknownvmt::IUnknownVmt, Class, Interface, Object, Ref,
|
|
8
|
-
Vmt,
|
|
9
|
-
};
|
|
6
|
+
use crate::{hresult::HRESULT, iunknown::IUnknown, Class, Interface, Object, Ref, Vmt};
|
|
10
7
|
|
|
11
8
|
#[repr(C)]
|
|
12
9
|
pub struct CObject<T: Class> {
|
|
@@ -31,7 +28,7 @@ impl<T: Class> CObject<T> {
|
|
|
31
28
|
unsafe { &*p }
|
|
32
29
|
}
|
|
33
30
|
|
|
34
|
-
pub const IUNKNOWN:
|
|
31
|
+
pub const IUNKNOWN: IUnknown<T::Interface> = IUnknown {
|
|
35
32
|
QueryInterface: Self::QueryInterface,
|
|
36
33
|
AddRef: Self::AddRef,
|
|
37
34
|
Release: Self::Release,
|
|
@@ -41,11 +38,11 @@ impl<T: Class> CObject<T> {
|
|
|
41
38
|
extern "stdcall" fn QueryInterface(
|
|
42
39
|
this: &Object<T::Interface>,
|
|
43
40
|
riid: &u128,
|
|
44
|
-
ppv_object: &mut *const Object
|
|
41
|
+
ppv_object: &mut *const Object,
|
|
45
42
|
) -> HRESULT {
|
|
46
|
-
let (p, r) = if *riid ==
|
|
43
|
+
let (p, r) = if *riid == <()>::GUID || *riid == T::Interface::GUID {
|
|
47
44
|
Self::AddRef(this);
|
|
48
|
-
(this.to_iunknown() as *const Object
|
|
45
|
+
(this.to_iunknown() as *const Object, HRESULT::S_OK)
|
|
49
46
|
} else {
|
|
50
47
|
(null(), HRESULT::E_NOINTERFACE)
|
|
51
48
|
};
|
|
File without changes
|
|
File without changes
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
use crate::{hresult::HRESULT,
|
|
1
|
+
use crate::{hresult::HRESULT, Object, GUID};
|
|
2
2
|
|
|
3
3
|
#[allow(non_snake_case)]
|
|
4
4
|
#[repr(C)]
|
|
5
|
-
pub struct
|
|
5
|
+
pub struct IUnknown<I: 'static> {
|
|
6
6
|
pub QueryInterface: unsafe extern "stdcall" fn(
|
|
7
7
|
this: &Object<I>,
|
|
8
8
|
riid: &GUID,
|
|
9
|
-
ppv_object: &mut *const Object
|
|
9
|
+
ppv_object: &mut *const Object,
|
|
10
10
|
) -> HRESULT,
|
|
11
11
|
pub AddRef: unsafe extern "stdcall" fn(this: &Object<I>) -> u32,
|
|
12
12
|
pub Release: unsafe extern "stdcall" fn(this: &Object<I>) -> u32,
|
|
@@ -4,12 +4,11 @@ mod guid;
|
|
|
4
4
|
mod hresult;
|
|
5
5
|
mod interface;
|
|
6
6
|
mod iunknown;
|
|
7
|
-
mod iunknownvmt;
|
|
8
7
|
mod object;
|
|
9
8
|
mod r#ref;
|
|
10
9
|
mod vmt;
|
|
11
10
|
|
|
12
11
|
pub use crate::{
|
|
13
|
-
class::Class, cobject::CObject, guid::GUID, interface::Interface,
|
|
14
|
-
vmt::Vmt,
|
|
12
|
+
class::Class, cobject::CObject, guid::GUID, interface::Interface, iunknown::IUnknown,
|
|
13
|
+
object::Object, r#ref::Ref, vmt::Vmt,
|
|
15
14
|
};
|
|
@@ -1,21 +1,18 @@
|
|
|
1
|
-
use crate::{
|
|
2
|
-
hresult::HRESULT, interface::Interface, iunknown::IUnknown, iunknownvmt::IUnknownVmt,
|
|
3
|
-
r#ref::Ref, vmt::Vmt,
|
|
4
|
-
};
|
|
1
|
+
use crate::{hresult::HRESULT, interface::Interface, iunknown::IUnknown, r#ref::Ref, vmt::Vmt};
|
|
5
2
|
use std::ptr::null;
|
|
6
3
|
|
|
7
4
|
#[repr(C)]
|
|
8
|
-
pub struct Object<I: 'static>(&'static Vmt<I>);
|
|
5
|
+
pub struct Object<I: 'static = ()>(&'static Vmt<I>);
|
|
9
6
|
|
|
10
7
|
impl<I> Object<I> {
|
|
11
|
-
pub unsafe fn iunknown(&self) -> &'static
|
|
8
|
+
pub unsafe fn iunknown(&self) -> &'static IUnknown<I> {
|
|
12
9
|
&self.0.iunknown
|
|
13
10
|
}
|
|
14
11
|
pub unsafe fn interface(&self) -> &'static I {
|
|
15
12
|
&self.0.interface
|
|
16
13
|
}
|
|
17
|
-
pub fn to_iunknown(&self) -> &Object
|
|
18
|
-
let p = self as *const Object<I> as *const Object
|
|
14
|
+
pub fn to_iunknown(&self) -> &Object {
|
|
15
|
+
let p = self as *const Object<I> as *const Object;
|
|
19
16
|
unsafe { &*p }
|
|
20
17
|
}
|
|
21
18
|
pub fn query_interface<J: Interface>(&self) -> Result<Ref<J>, HRESULT> {
|
|
@@ -28,7 +25,7 @@ impl<I> Object<I> {
|
|
|
28
25
|
e => Err(e),
|
|
29
26
|
}
|
|
30
27
|
}
|
|
31
|
-
pub fn query_iunknown(&self) -> Ref
|
|
28
|
+
pub fn query_iunknown(&self) -> Ref {
|
|
32
29
|
self.query_interface().unwrap()
|
|
33
30
|
}
|
|
34
31
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
use std::{cmp::Eq, fmt::Debug, ops::Deref};
|
|
1
|
+
use std::{cmp::Eq, fmt::{Debug, Formatter}, ops::Deref};
|
|
2
2
|
|
|
3
3
|
use crate::object::Object;
|
|
4
4
|
|
|
5
5
|
#[repr(transparent)]
|
|
6
|
-
pub struct Ref<I: 'static>(*const Object<I>);
|
|
6
|
+
pub struct Ref<I: 'static = ()>(*const Object<I>);
|
|
7
7
|
|
|
8
8
|
impl<I: 'static> Ref<I> {
|
|
9
9
|
pub unsafe fn from_raw(p: *const Object<I>) -> Ref<I> {
|
|
@@ -39,7 +39,7 @@ impl<I> From<&Object<I>> for Ref<I> {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
impl<I> Debug for Ref<I> {
|
|
42
|
-
fn fmt(&self, f: &mut
|
|
42
|
+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
43
43
|
f.debug_tuple("Ref").field(&self.0).finish()
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// interface definition:
|
|
2
|
+
|
|
3
|
+
mod library {
|
|
4
|
+
use nanocom::{CObject, Class, Interface, Object, Ref, GUID};
|
|
5
|
+
|
|
6
|
+
#[allow(non_snake_case)]
|
|
7
|
+
#[repr(C)]
|
|
8
|
+
pub struct IMy {
|
|
9
|
+
pub A: unsafe extern "stdcall" fn(this: &Object<IMy>) -> Ref<IMy>,
|
|
10
|
+
pub B: unsafe extern "stdcall" fn(this: &Object<IMy>) -> u32,
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
impl Interface for IMy {
|
|
14
|
+
const GUID: GUID = 0x01234567_89AB_CDEF_0123_456789ABCDEF;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
#[allow(non_snake_case)]
|
|
18
|
+
pub trait IMyEx {
|
|
19
|
+
fn A(&self) -> Ref<IMy>;
|
|
20
|
+
fn B(&self) -> u32;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#[allow(non_snake_case)]
|
|
24
|
+
impl IMyEx for Object<IMy> {
|
|
25
|
+
fn A(&self) -> Ref<IMy> {
|
|
26
|
+
unsafe { (self.interface().A)(self) }
|
|
27
|
+
}
|
|
28
|
+
fn B(&self) -> u32 {
|
|
29
|
+
unsafe { (self.interface().B)(self) }
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
pub trait IMyVmt: Class<Interface = IMy>
|
|
34
|
+
where
|
|
35
|
+
CObject<Self>: IMyEx,
|
|
36
|
+
{
|
|
37
|
+
const INTERFACE: IMy = IMy {
|
|
38
|
+
A: Self::A,
|
|
39
|
+
B: Self::B,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
impl<T: Class<Interface = IMy>> IMyVmt for T where CObject<T>: IMyEx {}
|
|
44
|
+
|
|
45
|
+
#[allow(non_snake_case)]
|
|
46
|
+
trait IMyVmtFn: Class<Interface = IMy>
|
|
47
|
+
where
|
|
48
|
+
CObject<Self>: IMyEx,
|
|
49
|
+
{
|
|
50
|
+
extern "stdcall" fn A(this: &Object<IMy>) -> Ref<IMy> {
|
|
51
|
+
unsafe { Self::to_cobject(this) }.A()
|
|
52
|
+
}
|
|
53
|
+
extern "stdcall" fn B(this: &Object<IMy>) -> u32 {
|
|
54
|
+
unsafe { Self::to_cobject(this) }.B()
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
impl<T: Class<Interface = IMy>> IMyVmtFn for T where CObject<T>: IMyEx {}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// interface implementation
|
|
62
|
+
mod number {
|
|
63
|
+
use nanocom::{CObject, Class, Ref, Vmt};
|
|
64
|
+
|
|
65
|
+
use super::library::{IMy, IMyEx, IMyVmt};
|
|
66
|
+
|
|
67
|
+
pub struct X(pub u32);
|
|
68
|
+
|
|
69
|
+
impl Class for X {
|
|
70
|
+
type Interface = IMy;
|
|
71
|
+
fn static_vmt() -> &'static Vmt<Self::Interface> {
|
|
72
|
+
static V: Vmt<IMy> = Vmt {
|
|
73
|
+
iunknown: X::IUNKNOWN,
|
|
74
|
+
interface: X::INTERFACE,
|
|
75
|
+
};
|
|
76
|
+
&V
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
#[allow(non_snake_case)]
|
|
81
|
+
impl IMyEx for CObject<X> {
|
|
82
|
+
fn A(&self) -> Ref<IMy> {
|
|
83
|
+
self.to_interface().into()
|
|
84
|
+
}
|
|
85
|
+
fn B(&self) -> u32 {
|
|
86
|
+
self.value.0
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
mod use_number {
|
|
92
|
+
use nanocom::Class;
|
|
93
|
+
|
|
94
|
+
use super::{library::IMyEx, number::X};
|
|
95
|
+
|
|
96
|
+
#[test]
|
|
97
|
+
fn test() {
|
|
98
|
+
let a = X(42).cobject_new();
|
|
99
|
+
let a1 = a.A();
|
|
100
|
+
assert_eq!(a, a1);
|
|
101
|
+
assert_eq!(a.B(), 42);
|
|
102
|
+
let b = X(43).cobject_new();
|
|
103
|
+
assert_ne!(a, b);
|
|
104
|
+
assert_eq!(b.B(), 43);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
mod destructor {
|
|
109
|
+
use std::{
|
|
110
|
+
rc::Rc,
|
|
111
|
+
sync::atomic::{AtomicU32, Ordering},
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
use nanocom::{CObject, Class, Ref, Vmt};
|
|
115
|
+
|
|
116
|
+
use super::library::{IMy, IMyEx, IMyVmt};
|
|
117
|
+
|
|
118
|
+
pub struct X {
|
|
119
|
+
p: Rc<AtomicU32>,
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
impl X {
|
|
123
|
+
pub fn new(p: Rc<AtomicU32>) -> Self {
|
|
124
|
+
p.fetch_add(1, Ordering::Relaxed);
|
|
125
|
+
Self { p }
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
impl Drop for X {
|
|
130
|
+
fn drop(&mut self) {
|
|
131
|
+
self.p.fetch_sub(1, Ordering::Relaxed);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
impl Class for X {
|
|
136
|
+
type Interface = IMy;
|
|
137
|
+
fn static_vmt() -> &'static Vmt<Self::Interface> {
|
|
138
|
+
static V: Vmt<IMy> = Vmt {
|
|
139
|
+
iunknown: X::IUNKNOWN,
|
|
140
|
+
interface: X::INTERFACE,
|
|
141
|
+
};
|
|
142
|
+
&V
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
#[allow(non_snake_case)]
|
|
147
|
+
impl IMyEx for CObject<X> {
|
|
148
|
+
fn A(&self) -> Ref<IMy> {
|
|
149
|
+
self.to_interface().into()
|
|
150
|
+
}
|
|
151
|
+
fn B(&self) -> u32 {
|
|
152
|
+
self.value.p.load(Ordering::Relaxed)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
mod use_destructor {
|
|
158
|
+
use std::{
|
|
159
|
+
rc::Rc,
|
|
160
|
+
sync::atomic::{AtomicU32, Ordering},
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
use nanocom::Class;
|
|
164
|
+
|
|
165
|
+
use super::{destructor::X, library::IMyEx};
|
|
166
|
+
|
|
167
|
+
#[test]
|
|
168
|
+
fn test() {
|
|
169
|
+
let p = Rc::new(AtomicU32::default());
|
|
170
|
+
{
|
|
171
|
+
assert_eq!(p.load(Ordering::Relaxed), 0);
|
|
172
|
+
let a = X::new(p.clone()).cobject_new();
|
|
173
|
+
assert_eq!(p.load(Ordering::Relaxed), 1);
|
|
174
|
+
let a1 = a.A();
|
|
175
|
+
assert_eq!(p.load(Ordering::Relaxed), 1);
|
|
176
|
+
assert_eq!(a, a1);
|
|
177
|
+
assert_eq!(a.B(), 1);
|
|
178
|
+
{
|
|
179
|
+
let b = X::new(p.clone()).cobject_new();
|
|
180
|
+
assert_eq!(p.load(Ordering::Relaxed), 2);
|
|
181
|
+
assert_ne!(a, b);
|
|
182
|
+
assert_eq!(b.B(), 2);
|
|
183
|
+
}
|
|
184
|
+
assert_eq!(p.load(Ordering::Relaxed), 1);
|
|
185
|
+
}
|
|
186
|
+
assert_eq!(p.load(Ordering::Relaxed), 0);
|
|
187
|
+
}
|
|
188
|
+
}
|
package/package.json
CHANGED
package/com/rust/com/Cargo.toml
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
#[cfg(test)]
|
|
2
|
-
mod test {
|
|
3
|
-
// interface definition:
|
|
4
|
-
|
|
5
|
-
mod library {
|
|
6
|
-
use com::{CObject, Class, Interface, Object, Ref, GUID};
|
|
7
|
-
|
|
8
|
-
#[allow(non_snake_case)]
|
|
9
|
-
#[repr(C)]
|
|
10
|
-
pub struct IMy {
|
|
11
|
-
pub A: unsafe extern "stdcall" fn(this: &Object<IMy>) -> Ref<IMy>,
|
|
12
|
-
pub B: unsafe extern "stdcall" fn(this: &Object<IMy>) -> u32,
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
impl Interface for IMy {
|
|
16
|
-
const GUID: GUID = 0x01234567_89AB_CDEF_0123_456789ABCDEF;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
#[allow(non_snake_case)]
|
|
20
|
-
pub trait IMyEx {
|
|
21
|
-
fn A(&self) -> Ref<IMy>;
|
|
22
|
-
fn B(&self) -> u32;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
#[allow(non_snake_case)]
|
|
26
|
-
impl IMyEx for Object<IMy> {
|
|
27
|
-
fn A(&self) -> Ref<IMy> {
|
|
28
|
-
unsafe { (self.interface().A)(self) }
|
|
29
|
-
}
|
|
30
|
-
fn B(&self) -> u32 {
|
|
31
|
-
unsafe { (self.interface().B)(self) }
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
pub trait IMyVmt: Class<Interface = IMy>
|
|
36
|
-
where
|
|
37
|
-
CObject<Self>: IMyEx,
|
|
38
|
-
{
|
|
39
|
-
const INTERFACE: IMy = IMy {
|
|
40
|
-
A: Self::A,
|
|
41
|
-
B: Self::B,
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
impl<T: Class<Interface = IMy>> IMyVmt for T where CObject<T>: IMyEx {}
|
|
46
|
-
|
|
47
|
-
#[allow(non_snake_case)]
|
|
48
|
-
trait IMyVmtFn: Class<Interface = IMy>
|
|
49
|
-
where
|
|
50
|
-
CObject<Self>: IMyEx,
|
|
51
|
-
{
|
|
52
|
-
extern "stdcall" fn A(this: &Object<IMy>) -> Ref<IMy> {
|
|
53
|
-
unsafe { Self::to_cobject(this) }.A()
|
|
54
|
-
}
|
|
55
|
-
extern "stdcall" fn B(this: &Object<IMy>) -> u32 {
|
|
56
|
-
unsafe { Self::to_cobject(this) }.B()
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
impl<T: Class<Interface = IMy>> IMyVmtFn for T where CObject<T>: IMyEx {}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// interface implementation
|
|
64
|
-
mod x {
|
|
65
|
-
use com::{CObject, Class, Ref, Vmt};
|
|
66
|
-
|
|
67
|
-
use super::library::{IMy, IMyEx, IMyVmt};
|
|
68
|
-
|
|
69
|
-
pub struct X(pub u32);
|
|
70
|
-
|
|
71
|
-
impl Class for X {
|
|
72
|
-
type Interface = IMy;
|
|
73
|
-
fn static_vmt() -> &'static Vmt<Self::Interface> {
|
|
74
|
-
static V: Vmt<IMy> = Vmt {
|
|
75
|
-
iunknown: X::IUNKNOWN,
|
|
76
|
-
interface: X::INTERFACE,
|
|
77
|
-
};
|
|
78
|
-
&V
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
#[allow(non_snake_case)]
|
|
83
|
-
impl IMyEx for CObject<X> {
|
|
84
|
-
fn A(&self) -> Ref<IMy> {
|
|
85
|
-
self.to_interface().into()
|
|
86
|
-
}
|
|
87
|
-
fn B(&self) -> u32 {
|
|
88
|
-
self.value.0
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
mod using {
|
|
94
|
-
use com::Class;
|
|
95
|
-
|
|
96
|
-
use crate::test::{library::IMyEx, x::X};
|
|
97
|
-
|
|
98
|
-
#[test]
|
|
99
|
-
fn test() {
|
|
100
|
-
let a = X(42).cobject_new();
|
|
101
|
-
let a1 = a.A();
|
|
102
|
-
assert_eq!(a, a1);
|
|
103
|
-
assert_eq!(a.B(), 42);
|
|
104
|
-
let b = X(43).cobject_new();
|
|
105
|
-
assert_ne!(a, b);
|
|
106
|
-
assert_eq!(b.B(), 43);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|