@@ -45,6 +45,7 @@ use crate::ir::var::Var;
45
45
use proc_macro2:: { self , Ident , Span } ;
46
46
use quote:: TokenStreamExt ;
47
47
48
+ use crate :: ir:: item:: ItemSet ;
48
49
use crate :: { Entry , HashMap , HashSet } ;
49
50
use std;
50
51
use std:: borrow:: Cow ;
@@ -484,11 +485,62 @@ impl CodeGenerator for Module {
484
485
485
486
let codegen_self = |result : & mut CodegenResult ,
486
487
found_any : & mut bool | {
487
- for child in self . children ( ) {
488
- if ctx. codegen_items ( ) . contains ( child) {
489
- * found_any = true ;
490
- ctx. resolve_item ( * child) . codegen ( ctx, result, & ( ) ) ;
488
+
489
+ // Partition our items into functions and non-functions.
490
+ let ( functions, non_functions) : ( ItemSet , ItemSet ) =
491
+ self . children ( ) . iter ( ) . partition ( |& child| {
492
+ let resolved = ctx. resolve_item ( * child) ;
493
+ match resolved. kind ( ) {
494
+ ItemKind :: Function ( _) => true ,
495
+ _ => false ,
496
+ }
497
+ } ) ;
498
+
499
+ for & child in & non_functions {
500
+ if !ctx. codegen_items ( ) . contains ( & child) {
501
+ continue ;
502
+ }
503
+ * found_any = true ;
504
+ ctx. resolve_item ( child) . codegen ( ctx, result, & ( ) ) ;
505
+ }
506
+
507
+ let counter = Cell :: new ( 0 ) ;
508
+ let mut functions_result = CodegenResult :: new ( & counter) ;
509
+ for & child in & functions {
510
+ if !ctx. codegen_items ( ) . contains ( & child) {
511
+ continue ;
491
512
}
513
+ * found_any = true ;
514
+ ctx. resolve_item ( child) . codegen (
515
+ ctx,
516
+ & mut functions_result,
517
+ & ( ) ,
518
+ ) ;
519
+ }
520
+
521
+ let tokens = & functions_result. items ;
522
+
523
+ // If we're using dynamic loading, wrap the generated bindings in a struct and append
524
+ // the libloading boilerplate.
525
+ if ctx. options ( ) . dynamic_loading {
526
+ let lib_ident = format_ident ! (
527
+ "{}" ,
528
+ ctx. options( ) . dynamic_library_name. as_ref( ) . unwrap( )
529
+ ) ;
530
+ result. push ( quote ! {
531
+ pub struct #lib_ident<' a> {
532
+ #( #tokens) *
533
+ }
534
+ } ) ;
535
+ utils:: append_libloading_boilerplate (
536
+ ctx,
537
+ & functions,
538
+ & mut * result,
539
+ ) ;
540
+ } else {
541
+ result. push ( quote ! {
542
+ #( #tokens) *
543
+ } ) ;
492
544
}
493
545
494
546
if item. id ( ) == ctx. root_module ( ) {
@@ -3697,11 +3749,19 @@ impl CodeGenerator for Function {
3697
3749
} ) ;
3698
3750
3699
3751
let ident = ctx. rust_ident ( canonical_name) ;
3700
- let tokens = quote ! {
3701
- #wasm_link_attribute
3702
- extern #abi {
3752
+
3753
+ let tokens = if ctx . options ( ) . dynamic_loading {
3754
+ quote ! {
3703
3755
#( #attributes) *
3704
- pub fn #ident ( #( #args ) , * ) #ret;
3756
+ #ident: libloading:: Symbol <' a, unsafe extern #abi fn ( #( #args ) , * ) #ret>,
3757
+ }
3758
+ } else {
3759
+ quote ! {
3760
+ #wasm_link_attribute
3761
+ extern #abi {
3762
+ #( #attributes) *
3763
+ pub fn #ident ( #( #args ) , * ) #ret;
3764
+ }
3705
3765
}
3706
3766
} ;
3707
3767
result. push ( tokens) ;
@@ -3956,6 +4016,7 @@ mod utils {
3956
4016
use super :: { error, ToRustTyOrOpaque } ;
3957
4017
use crate :: ir:: context:: BindgenContext ;
3958
4018
use crate :: ir:: function:: { Abi , FunctionSig } ;
4019
+ use crate :: ir:: item:: ItemSet ;
3959
4020
use crate :: ir:: item:: { Item , ItemCanonicalPath } ;
3960
4021
use crate :: ir:: ty:: TypeKind ;
3961
4022
use proc_macro2;
@@ -4453,4 +4514,41 @@ mod utils {
4453
4514
4454
4515
true
4455
4516
}
4517
+
4518
+ pub fn append_libloading_boilerplate (
4519
+ ctx : & BindgenContext ,
4520
+ functions : & ItemSet ,
4521
+ result : & mut Vec < proc_macro2:: TokenStream > ,
4522
+ ) {
4523
+ let mut function_definitions: Vec < proc_macro2:: TokenStream > =
4524
+ Vec :: new ( ) ;
4525
+
4526
+ for & function in functions {
4527
+ let function_item = ctx. resolve_item ( function) . expect_function ( ) ;
4528
+ let function_name = function_item. name ( ) ;
4529
+ let ident = format_ident ! ( "{}" , function_name) ;
4530
+ let function_definition = quote ! {
4531
+ #ident: lib. get( #function_name. as_bytes( ) )
4532
+ } ;
4533
+ function_definitions. push ( function_definition) ;
4534
+ }
4535
+
4536
+ let lib_ident = format_ident ! (
4537
+ "{}" ,
4538
+ ctx. options( ) . dynamic_library_name. as_ref( ) . unwrap( )
4539
+ ) ;
4540
+ let libloading_code = quote ! {
4541
+ impl <' a> #lib_ident<' a> {
4542
+ pub fn new( lib: & libloading:: Library ) -> #lib_ident {
4543
+ unsafe {
4544
+ #lib_ident {
4545
+ #( #function_definitions. unwrap( ) ) , *
4546
+ }
4547
+ }
4548
+ }
4549
+ }
4550
+ } ;
4551
+
4552
+ result. push ( libloading_code) ;
4553
+ }
4456
4554
}
0 commit comments