cobia_macro/
lib.rs

1use ::syn::parse::Parser;
2use proc_macro::TokenStream;
3use quote::quote;
4
5enum CapeOpenObjectMacroArg {
6	Interfaces(Vec<syn::Path>),
7	CreateArguments(Vec<syn::Ident>),
8	NewArguments(Vec<syn::Ident>),
9}
10
11impl syn::parse::Parse for CapeOpenObjectMacroArg {
12    fn parse(input: syn::parse::ParseStream) -> syn::parse::Result<Self> {
13		let name: syn::Ident = input.parse()?;
14		input.parse::<syn::Token![=]>()?;
15		if name=="interfaces" {
16			let content;
17			syn::braced!(content in input);
18			let paths : syn::punctuated::Punctuated::<syn::Path, syn::Token![,]> = content.parse_terminated(syn::Path::parse)?;
19			//convert paths to vector
20			let mut items : Vec<syn::Path> = Vec::with_capacity(paths.len());
21			for p in paths {
22				items.push(p);
23			}
24			Ok(CapeOpenObjectMacroArg::Interfaces(items))
25		} else if name=="create_arguments" {
26			let content;
27			syn::braced!(content in input);
28			let idents : syn::punctuated::Punctuated::<syn::Ident, syn::Token![,]> = content.parse_terminated(syn::Ident::parse)?;
29			//convert idents to vector
30			let mut items : Vec<syn::Ident> = Vec::with_capacity(idents.len());
31			for p in idents {
32				items.push(p);
33			}
34			Ok(CapeOpenObjectMacroArg::CreateArguments(items))
35		} else if name=="new_arguments" {
36			let content;
37			syn::braced!(content in input);
38			let idents : syn::punctuated::Punctuated::<syn::Ident, syn::Token![,]> = content.parse_terminated(syn::Ident::parse)?;
39			//convert idents to vector
40			let mut items : Vec<syn::Ident> = Vec::with_capacity(idents.len());
41			for p in idents {
42				items.push(p);
43			}
44			Ok(CapeOpenObjectMacroArg::NewArguments(items))
45		} else {
46			Err(syn::parse::Error::new(name.span(),format!("Unknown argument: {}",name)))
47		}
48    }
49}
50
51
52/// The cape_object_implementation macro generates the necessary code to implement a COBIA object.
53///
54/// It provides the ICapeInterface implementation, implements error handling, reference counting and
55/// QueryInterface.
56///
57/// This macro is used for a class implementation that is a COBIA object. The class must implement the
58/// ICapeObject interface, and the macro will generate the necessary code to implement the COBIA object.
59///
60/// Arguments to this macro may include the following:
61/// * `interfaces` - a set of CAPE-OPEN interfaces to be implemented. For each interface
62///                  the raw functions are automatically implemented, and the class is 
63///                  expected to implement the corresponding Impl trait. E.g. when 
64///                  specifying `cape_open_1_2::ICapeIdentification` one must provide
65///                  trait implementation `cape_open_1_2::ICapeIdentificationImpl`.
66/// * `create_arguments` - if specified, a set of arguments used to intialize the fields
67///                  of the struct. The arguments must match the name of the fields in the
68///                  struct, and will have the same type in the struct. Any arguments present
69///                  in the struct but not in the arguments will be initialized through
70///                  std::default::Default::default().
71/// * `new_arguments` - if specified, a set of arguments used to pass to a function `new` 
72///                  that is implemented by the `impl` block of the struct, with the same
73///                  arguments. These arguments must then be passed to the `create` or `try_create`.
74///
75/// Arguments are separated from their names by an equal sign, e.g.
76///
77/// ```text
78/// interfaces={
79///			cape_open_1_2::ICapeIdentification,
80///			cape_open_1_2::ICapeCollection<cape_open_1_2::CapeUnitPort>,
81///		}
82/// ```
83///
84/// In addition to using this macro, a COBIA object class must also initialize its generated memeber
85/// cobia_object_data in its constructor. This member can be set to Default::default()
86///
87/// The following traits must be implemented for the object:
88/// - std::fmt::Display, which is used to get a description of the object for error handing; it is advised to include the object's type and name
89/// - if the object is a primary PMC object that must be registered, also cobia::PMCRegisterationInfo
90/// - any other interfaces that the object implements, specified through the attribute
91///
92/// # Example:
93///
94/// See the distillation_shortcut_unit.rs file in the examples/distillation_shortcut_unit crate for an example of how to use this macro.
95/// See the salt_water_property_package.rs file in the examples/salt_water crate for an example of how to use this macro.
96
97#[proc_macro_attribute]
98pub fn cape_object_implementation(attr: TokenStream, item: TokenStream) -> TokenStream {
99	//extract list of interface type identifiers
100	let arguments = syn::punctuated::Punctuated::<CapeOpenObjectMacroArg, syn::Token![,]>::parse_terminated
101		.parse2(attr.into())
102		.expect("Incorrect format of cape_object_implementation attributes");
103	//see which fields are specified
104	let mut interfaces : Vec<syn::Path> = Vec::new();
105	let mut creation_arguments : Option<CapeOpenObjectMacroArg> = None;
106	for arg in arguments {
107		match arg {
108			CapeOpenObjectMacroArg::Interfaces(ifaces) => {
109				interfaces.extend(ifaces)
110			},
111			CapeOpenObjectMacroArg::CreateArguments(_args) => {
112				if creation_arguments.is_some() {
113					panic!("Multiple create_arguments or new_arguments specified");
114				}
115				creation_arguments= Some(CapeOpenObjectMacroArg::CreateArguments(_args));
116			},
117			CapeOpenObjectMacroArg::NewArguments(_args) => {
118				if creation_arguments.is_some() {
119					panic!("Multiple create_arguments or new_arguments specified");
120				}
121				creation_arguments= Some(CapeOpenObjectMacroArg::NewArguments(_args));
122			},
123		}
124	}
125	if interfaces.len()==0 {
126		panic!("No interfaces specified");
127	}
128
129	let mut struct_desc = syn::parse_macro_input!(item as syn::ItemStruct);
130	let structname = &struct_desc.ident;
131	let (impl_generics, ty_generics, where_clause) = struct_desc.generics.split_for_impl();
132	let cobiainfostruct = quote::format_ident!("{}{}", structname.to_string(), "CobiaObjectData");
133	//come up with a name for the pointer variable that is not likely the same as a field name
134	let ptr_name= structname
135		.to_string()
136		.chars()
137		.map(|c| if c.is_uppercase() { format!("_{}", c.to_lowercase()) } else { c.to_string() })
138		.collect::<String>();
139	let ptr_name= quote::format_ident!("{}_boxed_ptr", ptr_name);
140
141	//println!("   generating {}...", cobiainfostruct);
142
143
144	//add #cobiainfostruct field to struct, by name cobia_object_data
145
146	let mut object_creation = proc_macro2::TokenStream::new();
147	let mut create_arguments_def = proc_macro2::TokenStream::new();
148	let mut create_arguments = proc_macro2::TokenStream::new();
149	
150	match struct_desc.fields {
151		syn::Fields::Named(ref mut fields) => {
152			match creation_arguments {
153				None => {
154					object_creation= quote! {
155						std::default::Default::default()
156					};
157				}
158				Some(CapeOpenObjectMacroArg::CreateArguments(ref args)) | Some(CapeOpenObjectMacroArg::NewArguments(ref args))  => {
159					//make a dictionary of struct items and their types
160					let struct_items : std::collections::HashMap<String, syn::Type> = fields
161						.named
162						.iter()
163						.map(|f| {
164							(f.ident.as_ref().unwrap().to_string(), f.ty.clone())
165						})
166						.collect();
167					for id in args {
168						let typ = struct_items.get(&id.to_string());
169						if typ.is_none() {
170							panic!("Field '{}' not found in struct", &id);
171						}
172						let typ = typ.unwrap();
173						let arg = &id;
174						create_arguments_def.extend(quote! {
175							#arg : #typ,
176						});
177						create_arguments.extend(quote! {
178							#arg,
179						});
180					}
181					match creation_arguments {
182						Some(CapeOpenObjectMacroArg::CreateArguments(_)) => {
183							let create_arg_set=std::collections::HashSet::<String>::from_iter(args.iter().map(|x| x.to_string()));
184							let mut create_arguments = proc_macro2::TokenStream::new();
185							for f in fields.named.iter() {
186								let id=&f.ident;
187								if create_arg_set.contains(&f.ident.as_ref().unwrap().to_string()) {
188									create_arguments.extend(quote! {
189										#id,
190									});
191								} else {
192									create_arguments.extend(quote! {
193										#id : std::default::Default::default(),
194									});
195								}
196							};
197							create_arguments.extend(quote! {
198								cobia_object_data : std::default::Default::default(),
199							});
200							object_creation.extend(quote! {
201								Self {
202									#create_arguments
203								}
204							});
205						}
206						Some(CapeOpenObjectMacroArg::NewArguments(_)) => {
207							object_creation.extend(quote! {
208								Self::new(#create_arguments)
209							});
210						}
211						_ => {
212							panic!("Internal error");
213						}
214					}
215
216				}
217				_ => {
218					panic!("Internal error");
219				}
220			};
221			fields.named.push(
222				syn::Field::parse_named
223					.parse2(quote! {
224						/// Cobia object data for this object, which contains generated code to provide the native COBIA interfaces
225						cobia_object_data : #cobiainfostruct  
226					})
227					.expect("Unable to format info struct"),
228			);
229		}
230		syn::Fields::Unnamed(_) => {
231			return TokenStream::from(
232				syn::Error::new(
233					syn::spanned::Spanned::span(&struct_desc),
234					"unexpected tuple struct",
235				)
236				.to_compile_error(),
237			);
238		}
239		syn::Fields::Unit => {
240			return TokenStream::from(
241				syn::Error::new(
242					syn::spanned::Spanned::span(&struct_desc),
243					"unexpected unit struct",
244				)
245				.to_compile_error(),
246			);
247		}
248	}
249	//a bit of additional code for each interface to be generated
250	let mut struc_fields = proc_macro2::TokenStream::new();
251	let mut struc_init_statements = proc_macro2::TokenStream::new();
252	let mut struc_field_init = proc_macro2::TokenStream::new();
253	let mut interface_impls = proc_macro2::TokenStream::new();
254	//keep track of member variable name of cobiainfostruct
255	let mut member_set : std::collections::HashSet<String> = std::collections::HashSet::new();
256	member_set.insert("cape_object_data".to_string()); //add the cape_object_data field to the set
257	//loop over all interfaces to be implemented
258	for iface in interfaces {
259		//corresponding Impl trait
260		let mut impl_path = iface.clone();
261		impl_path.segments.last_mut().unwrap().ident =
262			quote::format_ident!("{}{}", impl_path.segments.last().unwrap().ident, "Impl");
263		//identifier name - take last two path elements and seprate by underscore. Make lower case
264		let mut struc_member_name: String;
265		if iface.segments.len()==1 {
266			struc_member_name=iface.segments.last().unwrap().ident.to_string();
267		} else {
268			struc_member_name=iface.segments[iface.segments.len()-2].ident.to_string();
269			struc_member_name.push_str(&iface.segments.last().unwrap().ident.to_string());
270		}
271		//make snake case
272		struc_member_name = struc_member_name
273			.chars()
274			.map(|c| if c.is_uppercase() { format!("_{}", c.to_lowercase()) } else { c.to_string() })
275			.collect::<String>();
276		//make unique
277		let mut i = 1;
278		while member_set.contains(&struc_member_name) {
279			struc_member_name = format!("{}_{}", struc_member_name, i);
280			i += 1;
281		}
282		member_set.insert(struc_member_name.clone());
283		//make into ident
284		let struc_member_name = quote::format_ident!("{}",struc_member_name);
285		let comment:proc_macro2::TokenStream=format!("/// Native {} interface", iface.segments.last().unwrap().ident).parse().unwrap();
286		//add field to struct
287		struc_fields.extend(quote! {
288			#comment
289			#struc_member_name : cobia::C::ICapeInterface,
290		});
291		//add initialization statement
292		struc_init_statements.extend(quote! {
293			<Self as #impl_path>::init(u);
294		});
295		//structure field intialization
296		struc_field_init.extend(quote! {
297			#struc_member_name : <#structname as #impl_path>::init_interface(),
298		});
299		//interface implementation
300		interface_impls.extend(quote! {
301			impl #impl_generics #impl_path for #structname #ty_generics #where_clause {
302				type T = #structname #ty_generics;
303				fn as_interface_pointer(&mut self) -> *mut cobia::C::ICapeInterface{
304					&mut self.cobia_object_data.#struc_member_name as *mut cobia::C::ICapeInterface
305				}
306
307			}
308		 });
309	}
310	let mut fn_create_instance = proc_macro2::TokenStream::new();
311	fn_create_instance.extend(quote! {
312			fn create_instance(#ptr_name : *mut *mut cobia::C::ICapeInterface,#create_arguments_def) -> cobia::CapeResult {
313				let obj:Self=#object_creation;
314				let object_ptr=Box::into_raw(Box::new(obj)); //into_raw locks the object in memory - no need to pin
315				let u : &mut Self= unsafe {&mut *object_ptr as &mut Self};
316				#struc_init_statements
317				unsafe {*#ptr_name=cobia::ICapeInterfaceImpl::init(u)};
318				cobia::COBIAERR_NOERROR
319			}
320	});
321	let mut cape_create_instance = proc_macro2::TokenStream::new();
322	let provide_cape_create_instance=match creation_arguments {
323		None => true,
324		Some(CapeOpenObjectMacroArg::CreateArguments(args)) => args.len()==0,
325		Some(CapeOpenObjectMacroArg::NewArguments(args)) => args.len()==0,
326		_ => {
327			panic!("Internal error");
328		}
329	};
330	if provide_cape_create_instance {
331		//move create instance into cobia::CapeCreateInstance trait
332		cape_create_instance.extend(quote! {
333			impl #impl_generics cobia::CapeCreateInstance for #structname #ty_generics #where_clause {
334				#fn_create_instance
335			}
336		});
337		//and don't but it in the impl block for Self
338		fn_create_instance = proc_macro2::TokenStream::new();
339	}
340
341	quote! {
342
343		#struct_desc
344
345		/// Data structure that contains generated code to provide the native COBIA interfaces
346		///
347		/// This object is generated by the `cape_object_implementation` macro.
348
349		struct #cobiainfostruct {
350			/// CapeObjectData for this object
351			cape_object_data : cobia::CapeObjectData,
352			#struc_fields
353		}
354
355		#cape_create_instance
356
357		use cobia::prelude::CapeSmartPointer;
358
359		impl #impl_generics #structname #ty_generics #where_clause {
360			#fn_create_instance
361			/// Create a new instance of the object and return a smart pointer to it
362			///
363			/// This function panics if the created object does not implement the
364			/// interface corresponding to the smart pointer to be returned. For a 
365			/// non-panic version, use the try_create() function.
366			pub(crate) fn create<T:cobia::prelude::CapeSmartPointer>(#create_arguments_def) -> T {
367				let mut #ptr_name: *mut C::ICapeInterface=std::ptr::null_mut();
368				Self::create_instance(&mut #ptr_name as *mut *mut C::ICapeInterface,#create_arguments);
369				match T::from_cape_interface_pointer(#ptr_name) {
370					Ok(smart_pointer) => smart_pointer,
371					Err(e) => {
372						//add and remove reference to avoid memory leak
373						let _obj=CapeObject::from_interface_pointer(#ptr_name);
374						panic!("Error creating smart pointer: {}", e);
375					},
376				}
377			}
378			/// Create a new instance of the object and return a smart pointer to it
379			///
380			/// This function returns an error if the created object does not implement the
381			/// interface corresponding to the smart pointer to be returned. 
382			pub(crate) fn try_create<T:cobia::prelude::CapeSmartPointer>(#create_arguments_def) -> Result<T,COBIAError> {
383				let mut #ptr_name: *mut C::ICapeInterface=std::ptr::null_mut();
384				Self::create_instance(&mut #ptr_name as *mut *mut C::ICapeInterface,#create_arguments);
385				let p=CapeObject::from_interface_pointer(#ptr_name);
386				T::from_object(&p)
387			}
388			/// Get a reference to the object
389			/// 
390			/// Note that as the reference is created from a smart pointer, the reference
391			/// is valid only as long as the smart pointer is valid. The reference
392			/// is not checked for multiple borrows
393			///
394			/// # Safety
395			///
396			/// The user must ensure that the smart pointer contains a valid 
397			/// object, and that the object is of the type that is being borrowed. It is 
398			/// not possible for the compiler to check this, as the borrow is done
399			/// through the native object pointer in the interface.
400			pub(crate) unsafe fn borrow<T:cobia::prelude::CapeSmartPointer>(smart_pointer:&T) -> &Self {
401				let p=smart_pointer.as_cape_interface_pointer();
402				let me=unsafe {(*p).me};
403				let p = me as *const Self;
404				unsafe {&*p}				
405			}
406			/// Get a mutable reference to the object
407			/// 
408			/// Note that as the reference is created from a smart pointer, the reference
409			/// is valid only as long as the smart pointer is valid. The reference
410			/// is not checked for multiple borrows
411			///
412			/// # Safety
413			///
414			/// This function is unsafe because it allows mutable access to the object. 
415			/// Also the user must ensure that the smart pointer contains a valid 
416			/// object, and that the object is of the type that is being borrowed. It is 
417			/// not possible for the compiler to check this, as the borrow is done
418			/// through the native object pointer in the interface.
419			pub(crate) unsafe fn borrow_mut<T:cobia::prelude::CapeSmartPointer>(smart_pointer:&mut T) -> &mut Self {
420				let p=smart_pointer.as_cape_interface_pointer();
421				let me=unsafe {(*p).me};
422				let p = me as *mut Self;
423				unsafe {&mut *p}				
424			}
425		}
426
427		impl Default for #cobiainfostruct {
428			   fn default() -> #cobiainfostruct {
429				#cobiainfostruct::new()
430			}
431		}
432
433		impl #cobiainfostruct {
434			fn new() ->  #cobiainfostruct {
435				#cobiainfostruct {
436					cape_object_data  : <#structname as cobia::ICapeInterfaceImpl>::create_object_data::<#structname>(),
437					#struc_field_init
438				}
439			}
440		}
441
442		impl #impl_generics cobia::ICapeInterfaceImpl for #structname #ty_generics #where_clause {
443			type T = #structname #ty_generics;
444			fn get_object_data(&mut self) -> &mut cobia::CapeObjectData {
445				&mut self.cobia_object_data.cape_object_data
446			}
447			fn get_self(&mut self) -> *mut #structname {
448				self as *mut #structname
449			}
450		}
451
452		#interface_impls
453
454	}
455	.into()
456}
457
458
459/// The cape_smart_pointer macro generates the necessary code to implement a COBIA smart pointer.
460///
461/// It exercises the ICapeInterface implementation, provides error handling, handles reference counting 
462/// and handles QueryInterface.
463///
464/// It is expected that the interface data member is named 'interface'. Also the wrapper provides
465///
466/// fn from_interface_pointer(interface: *mut Interface) ->  Self
467///
468/// where Interface is the interface type that the wrapper implements; from_interface_pointer should
469/// increase the reference count of the object. A second construction is needed that does not 
470/// increase the reference count, to construct the smart pointer from a return value that already
471/// has its reference count adjusted (e.g from query_interface or any function that returns an 
472/// interface pointer):
473///
474/// fn attach(interface: *mut Interface) ->  Self
475///
476/// The contained interface pointer is released upon Drop, except when the smart pointer is 
477/// detached. The smart pointer can be cloned, which increases the reference count of the
478/// contained interface pointer.
479///
480/// This macro is used for a wrapper class implementation that refer to a COBIA object. This
481/// macro will generate the necessary code to implement the CapeSmartPointer, Drop (=release) 
482/// and Clone (=addReference) traits.
483///
484/// Code that uses the cape_smart_pointer macro is typically provided (CobiaCollectionBase, 
485/// CobiaIdentification, ...) or generated from type information (see e.g. the cape_open_1_2 module).
486///
487/// The attribute passed to the interface is the interface ID. The interface type is derived
488/// from the 'interface' member, which must be a *mut of the interface type.
489/// 
490
491#[proc_macro_attribute]
492pub fn cape_smart_pointer(attr: TokenStream, item: TokenStream) -> TokenStream {
493	//parse input
494	let struct_desc = syn::parse_macro_input!(item as syn::ItemStruct);
495	let structname = &struct_desc.ident;
496	//println!("   generating smart pointer members for {}...", structname);
497	//determine interface type
498	let mut interface_type = None;
499	match struct_desc.fields {
500		syn::Fields::Named(ref fields) => {
501			//find the interface field
502			for field in fields.named.iter() {
503				if field.ident.as_ref().expect("Unable to obtain field identifier") == "interface" {
504					match field.ty {
505						syn::Type::Ptr(ref type_ptr) => {
506							match type_ptr.mutability {
507								Some(_) => {}
508								None => {
509									return TokenStream::from(
510										syn::Error::new(
511											syn::spanned::Spanned::span(&field),
512											"invalid interface member; must be a *mut to an interface type",
513										)
514										.to_compile_error(),
515									);
516								}
517							}
518							match *type_ptr.elem {
519								syn::Type::Path(ref type_path) => {
520									interface_type = Some(type_path.path.clone());
521								}
522								_ => {
523									return TokenStream::from(
524										syn::Error::new(
525											syn::spanned::Spanned::span(&field),
526											"invalid interface member; must be a *mut to an interface type",
527										)
528										.to_compile_error(),
529									);
530								}
531							}
532						}
533						_ => {
534							return TokenStream::from(
535								syn::Error::new(
536									syn::spanned::Spanned::span(&field),
537									"invalid interface member; must be a *mut to an interface type",
538								)
539								.to_compile_error(),
540							);
541						}
542
543					}
544					break;
545				}
546			}
547		}
548		syn::Fields::Unnamed(_) => {
549			return TokenStream::from(
550				syn::Error::new(
551					syn::spanned::Spanned::span(&struct_desc),
552					"unexpected tuple struct",
553				)
554				.to_compile_error(),
555			);
556		}
557		syn::Fields::Unit => {
558			return TokenStream::from(
559				syn::Error::new(
560					syn::spanned::Spanned::span(&struct_desc),
561					"unexpected unit struct",
562				)
563				.to_compile_error(),
564			);
565		}
566	}
567	if interface_type.is_none() {
568		return TokenStream::from(
569			syn::Error::new(
570				syn::spanned::Spanned::span(&struct_desc),
571				"interface field not found",
572			)
573			.to_compile_error(),
574		);
575	}
576	let interface_type=interface_type.expect("Invalid interface type");
577	//a bit of additional code for each interface to be generated
578	let interface_id=proc_macro2::TokenStream::from(attr);
579	let genericdef = struct_desc.generics.clone();
580	let mut genericref = syn::Generics{
581			lt_token: None,
582			params: syn::punctuated::Punctuated::new(),
583			gt_token: None,
584			where_clause: None,
585		};
586	if !genericdef.params.is_empty() {
587		genericref=genericdef.clone();
588		genericref.params.iter_mut().for_each(|param| {
589			match param {
590				syn::GenericParam::Type(type_param) => {
591					type_param.attrs.clear();
592					type_param.colon_token=None;
593					type_param.bounds=syn::punctuated::Punctuated::new();
594					type_param.eq_token=None;
595					type_param.default=None;
596				},
597				_ => {}
598			}
599		});
600	}
601	
602
603	//additional struct initializers
604	let mut extra_initializers = proc_macro2::TokenStream::new();
605	for field in struct_desc.fields.iter() {
606		let field = field.ident.as_ref().expect("Unable to obtain field identifier");
607		if  field == "interface" {
608			continue;
609		}
610		extra_initializers.extend(quote! {
611			#field : std::default::Default::default(),
612		});
613	}
614
615	quote! {
616
617		#struct_desc
618
619		impl #genericdef CapeSmartPointer for #structname #genericref {
620			type Interface = #interface_type;
621			fn as_interface_pointer(&self) -> *mut Self::Interface {
622				self.interface
623			}
624			fn as_cape_interface_pointer(&self) -> *mut C::ICapeInterface {
625				self.interface as *mut C::ICapeInterface
626			}
627			fn get_interface_id() -> &'static CapeUUID {
628				& #interface_id
629			}
630			fn from_object<T:CapeSmartPointer>(smart_pointer : &T) -> Result<Self,COBIAError> {
631				let mut interface : * mut C::ICapeInterface=std::ptr::null_mut();
632				let res=unsafe {
633					let other_interface=smart_pointer.as_cape_interface_pointer();
634					((*(*other_interface).vTbl).queryInterface.unwrap())((*other_interface).me,Self::get_interface_id(),&mut interface as *mut *mut C::ICapeInterface)
635				};
636				if res==COBIAERR_NOERROR {
637					if interface.is_null() {
638						Err(COBIAError::Code(COBIAERR_NULLPOINTER))
639					} else {
640						Ok(Self::attach(interface as *mut #interface_type))
641					}
642				} else {
643					Err(COBIAError::from_object(res,smart_pointer))
644				}
645			}
646			fn from_interface_pointer(interface: *mut Self::Interface) ->  Self {
647				if interface.is_null() {
648					panic!("Null pointer in creation of ICapeIdentificationSmartPtr");
649				}
650				unsafe {((*(*(interface as *mut C::ICapeInterface)).vTbl).addReference.unwrap())((*interface).me)};
651				Self {
652					interface,
653					#extra_initializers
654				}
655			}
656			fn attach(interface: *mut Self::Interface) ->  Self {
657				if interface.is_null() {
658					panic!("Null pointer in creation of ICapeIdentificationSmartPtr");
659				}
660				Self {
661					interface,
662					#extra_initializers
663				}
664			}
665			fn detach(self) ->  *mut Self::Interface {
666				let res=self.interface;
667				std::mem::forget(self); //don't call drop
668				res
669			}
670			fn from_cape_interface_pointer(interface : *mut C::ICapeInterface) -> Result<Self,COBIAError>  {
671				let mut my_interface : * mut C::ICapeInterface=std::ptr::null_mut();
672				let res=unsafe {
673					((*(*interface).vTbl).queryInterface.unwrap())((*interface).me,Self::get_interface_id(),&mut my_interface as *mut *mut C::ICapeInterface)
674				};
675				if res==COBIAERR_NOERROR {
676					if my_interface.is_null() {
677						Err(COBIAError::Code(COBIAERR_NULLPOINTER))
678					} else {
679						Ok(Self::attach(my_interface as *mut #interface_type))
680					}
681				} else {
682					Err(COBIAError::from_cape_interface_pointer(res,interface))
683				}
684			}
685			fn last_error(&self) -> Option<CapeError> {
686				let mut interface : * mut C::ICapeError=std::ptr::null_mut();
687				let res=unsafe {
688					((*(*(self.interface as *mut C::ICapeInterface)).vTbl).getLastError.unwrap())((*self.interface).me,&mut interface as *mut *mut C::ICapeError)
689				};
690				if res==COBIAERR_NOERROR {
691					if interface.is_null() {
692						None
693					} else {
694						Some(CapeError::attach(interface))
695					}
696				} else {
697					None
698				}
699			}
700		}
701
702		impl #genericdef Drop for #structname #genericref {
703			fn drop(&mut self) {
704				let interface=self.as_cape_interface_pointer();
705				unsafe {
706					((*(*interface).vTbl).release.unwrap())((*interface).me);
707				}
708			}
709		}
710
711		impl #genericdef Clone for #structname #genericref {
712			fn clone(&self) -> Self {
713				let interface=self.as_cape_interface_pointer();
714				Self::from_interface_pointer(interface as *mut #interface_type)
715			}
716		}
717
718	}
719	.into()
720}
721