@@ -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,63 @@ 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
+ extern crate libloading;
532
+ pub struct #lib_ident<' a> {
533
+ #( #tokens) *
534
+ }
535
+ } ) ;
536
+ utils:: append_libloading_boilerplate (
537
+ ctx,
538
+ & functions,
539
+ & mut * result,
540
+ ) ;
541
+ } else {
542
+ result. push ( quote ! {
543
+ #( #tokens) *
544
+ } ) ;
492
545
}
493
546
494
547
if item. id ( ) == ctx. root_module ( ) {
@@ -3697,11 +3750,19 @@ impl CodeGenerator for Function {
3697
3750
} ) ;
3698
3751
3699
3752
let ident = ctx. rust_ident ( canonical_name) ;
3700
- let tokens = quote ! {
3701
- #wasm_link_attribute
3702
- extern #abi {
3753
+
3754
+ let tokens = if ctx . options ( ) . dynamic_loading {
3755
+ quote ! {
3703
3756
#( #attributes) *
3704
- pub fn #ident ( #( #args ) , * ) #ret;
3757
+ #ident: libloading:: Symbol <' a, unsafe extern #abi fn ( #( #args ) , * ) #ret>,
3758
+ }
3759
+ } else {
3760
+ quote ! {
3761
+ #wasm_link_attribute
3762
+ extern #abi {
3763
+ #( #attributes) *
3764
+ pub fn #ident ( #( #args ) , * ) #ret;
3765
+ }
3705
3766
}
3706
3767
} ;
3707
3768
result. push ( tokens) ;
@@ -3956,6 +4017,7 @@ mod utils {
3956
4017
use super :: { error, ToRustTyOrOpaque } ;
3957
4018
use crate :: ir:: context:: BindgenContext ;
3958
4019
use crate :: ir:: function:: { Abi , FunctionSig } ;
4020
+ use crate :: ir:: item:: ItemSet ;
3959
4021
use crate :: ir:: item:: { Item , ItemCanonicalPath } ;
3960
4022
use crate :: ir:: ty:: TypeKind ;
3961
4023
use proc_macro2;
@@ -4453,4 +4515,41 @@ mod utils {
4453
4515
4454
4516
true
4455
4517
}
4518
+
4519
+ pub fn append_libloading_boilerplate (
4520
+ ctx : & BindgenContext ,
4521
+ functions : & ItemSet ,
4522
+ result : & mut Vec < proc_macro2:: TokenStream > ,
4523
+ ) {
4524
+ let mut function_definitions: Vec < proc_macro2:: TokenStream > =
4525
+ Vec :: new ( ) ;
4526
+
4527
+ for & function in functions {
4528
+ let function_item = ctx. resolve_item ( function) . expect_function ( ) ;
4529
+ let function_name = function_item. name ( ) ;
4530
+ let ident = format_ident ! ( "{}" , function_name) ;
4531
+ let function_definition = quote ! {
4532
+ #ident: lib. get( #function_name. as_bytes( ) )
4533
+ } ;
4534
+ function_definitions. push ( function_definition) ;
4535
+ }
4536
+
4537
+ let lib_ident = format_ident ! (
4538
+ "{}" ,
4539
+ ctx. options( ) . dynamic_library_name. as_ref( ) . unwrap( )
4540
+ ) ;
4541
+ let libloading_code = quote ! {
4542
+ impl <' a> #lib_ident<' a> {
4543
+ pub fn new( lib: & libloading:: Library ) -> #lib_ident {
4544
+ unsafe {
4545
+ #lib_ident {
4546
+ #( #function_definitions. unwrap( ) ) , *
4547
+ }
4548
+ }
4549
+ }
4550
+ }
4551
+ } ;
4552
+
4553
+ result. push ( libloading_code) ;
4554
+ }
4456
4555
}
0 commit comments