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