@@ -15,7 +15,7 @@ use crate::typedef::NewTypedefResult;
15
15
use crate :: writer:: rust_native:: element:: RustElement ;
16
16
use crate :: {
17
17
get_definition_text, line_reader, settings, AbstractRefWrapper , Class , ClassKindOverride , Const , Element , EntityExt ,
18
- EntityWalkerExt , EntityWalkerVisitor , Enum , Func , GeneratorEnv , LineReaderAction , SmartPtr , Tuple , Typedef , Vector ,
18
+ EntityWalkerExt , EntityWalkerVisitor , Enum , Func , GeneratorEnv , SmartPtr , Tuple , Typedef , Vector ,
19
19
} ;
20
20
21
21
#[ derive( Debug ) ]
@@ -41,7 +41,7 @@ impl<'tu, 'ge> TryFrom<TypeRef<'tu, 'ge>> for GeneratedType<'tu, 'ge> {
41
41
42
42
/// Visitor of the different supported OpenCV entities, used in conjunction with [Generator]
43
43
#[ allow( unused) ]
44
- pub trait GeneratorVisitor {
44
+ pub trait GeneratorVisitor < ' tu > : Sized {
45
45
/// Check whether the visitor is interested in entities from the specified file
46
46
fn wants_file ( & mut self , path : & Path ) -> bool {
47
47
true
@@ -51,36 +51,39 @@ pub trait GeneratorVisitor {
51
51
fn visit_module_comment ( & mut self , comment : String ) { }
52
52
53
53
/// Top-level constant
54
- fn visit_const ( & mut self , cnst : Const ) { }
54
+ fn visit_const ( & mut self , cnst : Const < ' tu > ) { }
55
55
56
56
/// Top-level enum
57
- fn visit_enum ( & mut self , enm : Enum ) { }
57
+ fn visit_enum ( & mut self , enm : Enum < ' tu > ) { }
58
58
59
59
/// Top-level function
60
- fn visit_func ( & mut self , func : Func ) { }
60
+ fn visit_func ( & mut self , func : Func < ' tu , ' _ > ) { }
61
61
62
62
/// Top-level type alias
63
- fn visit_typedef ( & mut self , typedef : Typedef ) { }
63
+ fn visit_typedef ( & mut self , typedef : Typedef < ' tu , ' _ > ) { }
64
64
65
65
/// Top-level class or an internal class of another class
66
- fn visit_class ( & mut self , class : Class ) { }
66
+ fn visit_class ( & mut self , class : Class < ' tu , ' _ > ) { }
67
67
68
68
/// Dependent generated type like `std::vector<Mat>` or `std::tuple<1, 2, 3>`
69
- fn visit_generated_type ( & mut self , typ : GeneratedType ) { }
69
+ fn visit_generated_type ( & mut self , typ : GeneratedType < ' tu , ' _ > ) { }
70
+
71
+ /// Called at the end of the visitation
72
+ fn goodbye ( self ) { }
70
73
}
71
74
72
75
/// Bridge between [EntityWalkerVisitor] and [GeneratorVisitor]
73
76
///
74
77
/// It takes [Entity]s supplied by the entity walker, extracts their export data (whether the entity should appear in bindings at
75
78
/// all or is internal) and calls the corresponding method in [GeneratorVisitor] based on their type. This is the 2nd pass of the
76
79
/// binding generation.
77
- struct OpenCvWalker < ' tu , ' r , V : GeneratorVisitor > {
80
+ struct OpenCvWalker < ' tu , ' r , V > {
78
81
opencv_module_header_dir : & ' r Path ,
79
82
visitor : V ,
80
83
gen_env : GeneratorEnv < ' tu > ,
81
84
}
82
85
83
- impl < ' tu , V : GeneratorVisitor > EntityWalkerVisitor < ' tu > for OpenCvWalker < ' tu , ' _ , V > {
86
+ impl < ' tu , V : GeneratorVisitor < ' tu > > EntityWalkerVisitor < ' tu > for OpenCvWalker < ' tu , ' _ , V > {
84
87
fn wants_file ( & mut self , path : & Path ) -> bool {
85
88
self . visitor . wants_file ( path) || path. ends_with ( "ocvrs_common.hpp" )
86
89
}
@@ -148,9 +151,61 @@ impl<'tu, V: GeneratorVisitor> EntityWalkerVisitor<'tu> for OpenCvWalker<'tu, '_
148
151
}
149
152
ControlFlow :: Continue ( ( ) )
150
153
}
154
+
155
+ fn goodbye ( mut self ) {
156
+ // Some module level comments like "bioinspired" are not attached to anything and libclang
157
+ // doesn't seem to offer a way to extract them, do it the hard way then.
158
+ // That's actually the case for all modules starting with OpenCV 4.8.0 so this is now a single
159
+ // method of extracting comments
160
+ let mut comment = String :: with_capacity ( 2048 ) ;
161
+ let mut found_module_comment = false ;
162
+ let module_path = self . opencv_module_header_dir . join ( format ! ( "{}.hpp" , self . gen_env. module( ) ) ) ;
163
+ if let Ok ( module_file) = File :: open ( module_path) {
164
+ let f = BufReader :: new ( module_file) ;
165
+ let mut defgroup_found = false ;
166
+ line_reader ( f, |line| {
167
+ if !found_module_comment && line. trim_start ( ) . starts_with ( "/**" ) {
168
+ found_module_comment = true ;
169
+ defgroup_found = false ;
170
+ }
171
+ if found_module_comment {
172
+ if comment. contains ( "@defgroup" ) {
173
+ defgroup_found = true ;
174
+ }
175
+ comment. push_str ( line) ;
176
+ if line. trim_end ( ) . ends_with ( "*/" ) {
177
+ if defgroup_found {
178
+ return ControlFlow :: Break ( ( ) ) ;
179
+ } else {
180
+ comment. clear ( ) ;
181
+ found_module_comment = false ;
182
+ }
183
+ }
184
+ }
185
+ ControlFlow :: Continue ( ( ) )
186
+ } ) ;
187
+ }
188
+ if found_module_comment {
189
+ self . visitor . visit_module_comment ( comment) ;
190
+ }
191
+ for inject_func_fact in settings:: FUNC_INJECT . get ( self . gen_env . module ( ) ) . into_iter ( ) . flatten ( ) {
192
+ let inject_func: Func = inject_func_fact ( ) ;
193
+ if !inject_func. kind ( ) . as_class_method ( ) . is_some ( ) {
194
+ self . visitor . visit_func ( inject_func) ;
195
+ }
196
+ }
197
+ if let Some ( tweaks) = settings:: GENERATOR_MODULE_TWEAKS . get ( self . gen_env . module ( ) ) {
198
+ for generated in & tweaks. generate_types {
199
+ if let Ok ( generated) = GeneratedType :: try_from ( generated ( ) ) {
200
+ self . visitor . visit_generated_type ( generated) ;
201
+ }
202
+ }
203
+ }
204
+ self . visitor . goodbye ( ) ;
205
+ }
151
206
}
152
207
153
- impl < ' tu , ' r , V : GeneratorVisitor > OpenCvWalker < ' tu , ' r , V > {
208
+ impl < ' tu , ' r , V : GeneratorVisitor < ' tu > > OpenCvWalker < ' tu , ' r , V > {
154
209
pub fn new ( opencv_module_header_dir : & ' r Path , visitor : V , gen_env : GeneratorEnv < ' tu > ) -> Self {
155
210
Self {
156
211
opencv_module_header_dir,
@@ -159,7 +214,7 @@ impl<'tu, 'r, V: GeneratorVisitor> OpenCvWalker<'tu, 'r, V> {
159
214
}
160
215
}
161
216
162
- fn process_const ( visitor : & mut V , const_decl : Entity ) {
217
+ fn process_const ( visitor : & mut V , const_decl : Entity < ' tu > ) {
163
218
let cnst = Const :: new ( const_decl) ;
164
219
if cnst. exclude_kind ( ) . is_included ( ) {
165
220
visitor. visit_const ( cnst) ;
@@ -202,7 +257,7 @@ impl<'tu, 'r, V: GeneratorVisitor> OpenCvWalker<'tu, 'r, V> {
202
257
}
203
258
}
204
259
205
- fn process_enum ( visitor : & mut V , enum_decl : Entity ) {
260
+ fn process_enum ( visitor : & mut V , enum_decl : Entity < ' tu > ) {
206
261
let enm = Enum :: new ( enum_decl) ;
207
262
if enm. exclude_kind ( ) . is_included ( ) {
208
263
for cnst in enm. consts ( ) {
@@ -294,57 +349,6 @@ impl<'tu, 'r, V: GeneratorVisitor> OpenCvWalker<'tu, 'r, V> {
294
349
}
295
350
}
296
351
297
- impl < V : GeneratorVisitor > Drop for OpenCvWalker < ' _ , ' _ , V > {
298
- fn drop ( & mut self ) {
299
- // Some module level comments like "bioinspired" are not attached to anything and libclang
300
- // doesn't seem to offer a way to extract them, do it the hard way then.
301
- // That's actually the case for all modules starting with OpenCV 4.8.0 so this is now a single
302
- // method of extracting comments
303
- let mut comment = String :: with_capacity ( 2048 ) ;
304
- let module_path = self . opencv_module_header_dir . join ( format ! ( "{}.hpp" , self . gen_env. module( ) ) ) ;
305
- let f = BufReader :: new ( File :: open ( module_path) . expect ( "Can't open main module file" ) ) ;
306
- let mut found_module_comment = false ;
307
- let mut defgroup_found = false ;
308
- line_reader ( f, |line| {
309
- if !found_module_comment && line. trim_start ( ) . starts_with ( "/**" ) {
310
- found_module_comment = true ;
311
- defgroup_found = false ;
312
- }
313
- if found_module_comment {
314
- if comment. contains ( "@defgroup" ) {
315
- defgroup_found = true ;
316
- }
317
- comment. push_str ( line) ;
318
- if line. trim_end ( ) . ends_with ( "*/" ) {
319
- if defgroup_found {
320
- return LineReaderAction :: Break ;
321
- } else {
322
- comment. clear ( ) ;
323
- found_module_comment = false ;
324
- }
325
- }
326
- }
327
- LineReaderAction :: Continue
328
- } ) ;
329
- if found_module_comment {
330
- self . visitor . visit_module_comment ( comment) ;
331
- }
332
- for inject_func_fact in settings:: FUNC_INJECT . get ( self . gen_env . module ( ) ) . into_iter ( ) . flatten ( ) {
333
- let inject_func: Func = inject_func_fact ( ) ;
334
- if !inject_func. kind ( ) . as_class_method ( ) . is_some ( ) {
335
- self . visitor . visit_func ( inject_func) ;
336
- }
337
- }
338
- if let Some ( tweaks) = settings:: GENERATOR_MODULE_TWEAKS . get ( self . gen_env . module ( ) ) {
339
- for generated in & tweaks. generate_types {
340
- if let Ok ( generated) = GeneratedType :: try_from ( generated ( ) ) {
341
- self . visitor . visit_generated_type ( generated) ;
342
- }
343
- }
344
- }
345
- }
346
- }
347
-
348
352
/// Main workhorse for generating OpenCV bindings for a specific module
349
353
///
350
354
/// Full binding generation for a module is happening in the following major phases:
@@ -436,9 +440,9 @@ impl Generator {
436
440
// need to have c++14 here because VS headers contain features that require it
437
441
args. push ( "-std=c++14" . into ( ) ) ;
438
442
// allow us to use some custom clang args
439
- if let Some ( clang_arg_str ) = env:: var_os ( "OPENCV_CLANG_ARGS" ) {
440
- let clang_arg = clang_arg_str . to_str ( ) . expect ( "Try to get OPENCV_CLANG_ARGS failed." ) ;
441
- Shlex :: new ( clang_arg) . into_iter ( ) . for_each ( |i| args . push ( i . into ( ) ) )
443
+ let clang_arg = env:: var_os ( "OPENCV_CLANG_ARGS" ) ;
444
+ if let Some ( clang_arg) = clang_arg . as_ref ( ) . and_then ( |s| s . to_str ( ) ) {
445
+ args . extend ( Shlex :: new ( clang_arg) . map ( Cow :: Owned ) ) ;
442
446
}
443
447
args
444
448
}
@@ -462,7 +466,7 @@ impl Generator {
462
466
}
463
467
464
468
/// Runs the full binding generation process using the supplied `visitor`
465
- pub fn generate ( & self , module : & str , visitor : impl GeneratorVisitor ) {
469
+ pub fn generate ( & self , module : & str , visitor : impl for < ' tu > GeneratorVisitor < ' tu > ) {
466
470
self . pre_process ( module, true , |root_entity| {
467
471
let gen_env = GeneratorEnv :: new ( root_entity, module) ;
468
472
let opencv_walker = OpenCvWalker :: new ( & self . opencv_module_header_dir , visitor, gen_env) ;
0 commit comments