@@ -103,6 +103,9 @@ struct CodegenResult<'a> {
103
103
/// Whether Objective C types have been seen at least once.
104
104
saw_objc : bool ,
105
105
106
+ /// Whether Apple block types have been seen at least once.
107
+ saw_block : bool ,
108
+
106
109
/// Whether a bitfield allocation unit has been seen at least once.
107
110
saw_bitfield_unit : bool ,
108
111
@@ -140,6 +143,7 @@ impl<'a> CodegenResult<'a> {
140
143
saw_bindgen_union : false ,
141
144
saw_incomplete_array : false ,
142
145
saw_objc : false ,
146
+ saw_block : false ,
143
147
saw_bitfield_unit : false ,
144
148
codegen_id : codegen_id,
145
149
items_seen : Default :: default ( ) ,
@@ -166,6 +170,10 @@ impl<'a> CodegenResult<'a> {
166
170
self . saw_objc = true ;
167
171
}
168
172
173
+ fn saw_block ( & mut self ) {
174
+ self . saw_block = true ;
175
+ }
176
+
169
177
fn saw_bitfield_unit ( & mut self ) {
170
178
self . saw_bitfield_unit = true ;
171
179
}
@@ -215,6 +223,7 @@ impl<'a> CodegenResult<'a> {
215
223
self . saw_union |= new. saw_union ;
216
224
self . saw_incomplete_array |= new. saw_incomplete_array ;
217
225
self . saw_objc |= new. saw_objc ;
226
+ self . saw_block |= new. saw_block ;
218
227
self . saw_bitfield_unit |= new. saw_bitfield_unit ;
219
228
220
229
new. items
@@ -293,7 +302,6 @@ impl AppendImplicitTemplateParams for quote::Tokens {
293
302
TypeKind :: Opaque |
294
303
TypeKind :: Function ( ..) |
295
304
TypeKind :: Enum ( ..) |
296
- TypeKind :: BlockPointer |
297
305
TypeKind :: ObjCId |
298
306
TypeKind :: ObjCSel |
299
307
TypeKind :: TemplateInstantiation ( ..) => return ,
@@ -406,6 +414,9 @@ impl CodeGenerator for Module {
406
414
if result. saw_objc {
407
415
utils:: prepend_objc_header ( ctx, & mut * result) ;
408
416
}
417
+ if result. saw_block {
418
+ utils:: prepend_block_header ( ctx, & mut * result) ;
419
+ }
409
420
if result. saw_bitfield_unit {
410
421
utils:: prepend_bitfield_unit_type ( & mut * result) ;
411
422
}
@@ -597,7 +608,6 @@ impl CodeGenerator for Type {
597
608
TypeKind :: Array ( ..) |
598
609
TypeKind :: Vector ( ..) |
599
610
TypeKind :: Pointer ( ..) |
600
- TypeKind :: BlockPointer |
601
611
TypeKind :: Reference ( ..) |
602
612
TypeKind :: Function ( ..) |
603
613
TypeKind :: ResolvedTypeRef ( ..) |
@@ -610,6 +620,38 @@ impl CodeGenerator for Type {
610
620
TypeKind :: TemplateInstantiation ( ref inst) => {
611
621
inst. codegen ( ctx, result, item)
612
622
}
623
+ TypeKind :: BlockPointer ( inner) => {
624
+ let inner_item = inner. into_resolver ( )
625
+ . through_type_refs ( )
626
+ . resolve ( ctx) ;
627
+ let name = item. canonical_name ( ctx) ;
628
+
629
+ let inner_rust_type = {
630
+ // Its possible that we have better layout information than
631
+ // the inner type does, so fall back to an opaque blob based
632
+ // on our layout if converting the inner item fails.
633
+ if let TypeKind :: Function ( fnsig) = inner_item. kind ( ) . expect_type ( ) . kind ( ) {
634
+ utils:: fnsig_block ( ctx, fnsig)
635
+ } else {
636
+ panic ! ( "invalid block typedef" )
637
+ }
638
+ } ;
639
+
640
+ let rust_name = ctx. rust_ident ( & name) ;
641
+
642
+ let mut tokens = if let Some ( comment) = item. comment ( ctx) {
643
+ attributes:: doc ( comment)
644
+ } else {
645
+ quote ! { }
646
+ } ;
647
+
648
+ tokens. append_all ( quote ! {
649
+ pub type #rust_name = #inner_rust_type ;
650
+ } ) ;
651
+
652
+ result. push ( tokens) ;
653
+ result. saw_block ( ) ;
654
+ }
613
655
TypeKind :: Comp ( ref ci) => ci. codegen ( ctx, result, item) ,
614
656
TypeKind :: TemplateAlias ( inner, _) |
615
657
TypeKind :: Alias ( inner) => {
@@ -636,9 +678,10 @@ impl CodeGenerator for Type {
636
678
637
679
// If this is a known named type, disallow generating anything
638
680
// for it too.
639
- let spelling = self . name ( ) . expect ( "Unnamed alias?" ) ;
640
- if utils:: type_from_named ( ctx, spelling) . is_some ( ) {
641
- return ;
681
+ if let Some ( spelling) = self . name ( ) {
682
+ if utils:: type_from_named ( ctx, spelling) . is_some ( ) {
683
+ return ;
684
+ }
642
685
}
643
686
644
687
let mut outer_params = item. used_template_params ( ctx) ;
@@ -3071,23 +3114,25 @@ impl TryToRustTy for Type {
3071
3114
}
3072
3115
TypeKind :: ResolvedTypeRef ( inner) => inner. try_to_rust_ty ( ctx, & ( ) ) ,
3073
3116
TypeKind :: TemplateAlias ( ..) |
3074
- TypeKind :: Alias ( ..) => {
3117
+ TypeKind :: Alias ( ..) |
3118
+ TypeKind :: BlockPointer ( ..) => {
3075
3119
let template_params = item. used_template_params ( ctx)
3076
3120
. into_iter ( )
3077
3121
. filter ( |param| param. is_template_param ( ctx, & ( ) ) )
3078
3122
. collect :: < Vec < _ > > ( ) ;
3079
3123
3080
- let spelling = self . name ( ) . expect ( "Unnamed alias?" ) ;
3081
3124
if item. is_opaque ( ctx, & ( ) ) && !template_params. is_empty ( ) {
3082
3125
self . try_to_opaque ( ctx, item)
3083
- } else if let Some ( ty) = utils:: type_from_named (
3084
- ctx,
3085
- spelling,
3086
- )
3087
- {
3088
- Ok ( ty)
3089
3126
} else {
3090
- utils:: build_path ( item, ctx)
3127
+ if let Some ( spelling) = self . name ( ) {
3128
+ if let Some ( ty) = utils:: type_from_named ( ctx, spelling) {
3129
+ Ok ( ty)
3130
+ } else {
3131
+ utils:: build_path ( item, ctx)
3132
+ }
3133
+ } else {
3134
+ utils:: build_path ( item, ctx)
3135
+ }
3091
3136
}
3092
3137
}
3093
3138
TypeKind :: Comp ( ref info) => {
@@ -3101,13 +3146,6 @@ impl TryToRustTy for Type {
3101
3146
utils:: build_path ( item, ctx)
3102
3147
}
3103
3148
TypeKind :: Opaque => self . try_to_opaque ( ctx, item) ,
3104
- TypeKind :: BlockPointer => {
3105
- let void = raw_type ( ctx, "c_void" ) ;
3106
- Ok ( void. to_ptr (
3107
- /* is_const = */
3108
- false
3109
- ) )
3110
- }
3111
3149
TypeKind :: Pointer ( inner) |
3112
3150
TypeKind :: Reference ( inner) => {
3113
3151
let is_const = ctx. resolve_type ( inner) . is_const ( ) ;
@@ -3517,7 +3555,7 @@ pub(crate) fn codegen(context: BindgenContext) -> (Vec<quote::Tokens>, BindgenOp
3517
3555
}
3518
3556
3519
3557
mod utils {
3520
- use super :: { ToRustTyOrOpaque , error} ;
3558
+ use super :: { ToRustTyOrOpaque , error, helpers } ;
3521
3559
use ir:: context:: BindgenContext ;
3522
3560
use ir:: function:: FunctionSig ;
3523
3561
use ir:: item:: { Item , ItemCanonicalPath } ;
@@ -3560,6 +3598,46 @@ mod utils {
3560
3598
result. extend ( old_items. into_iter ( ) ) ;
3561
3599
}
3562
3600
3601
+ pub fn prepend_block_header (
3602
+ ctx : & BindgenContext ,
3603
+ result : & mut Vec < quote:: Tokens > ,
3604
+ ) {
3605
+ let use_block = if ctx. options ( ) . block_extern_crate {
3606
+ quote ! {
3607
+ #[ macro_use]
3608
+ extern crate block;
3609
+ }
3610
+ } else {
3611
+ quote ! {
3612
+ use block;
3613
+ }
3614
+ } ;
3615
+
3616
+ let void = helpers:: ast_ty:: raw_type ( ctx, "c_void" ) ;
3617
+ let def_block = quote ! {
3618
+ pub fn block<A , R , F >( closure: F ) -> * const :: block:: Block <A , R >
3619
+ where
3620
+ A : :: block:: BlockArguments ,
3621
+ F : ' static + :: block:: IntoConcreteBlock <A , Ret = R >,
3622
+ {
3623
+ let block = :: block:: ConcreteBlock :: new( closure) ;
3624
+ let block = block. copy( ) ;
3625
+ let ptr = ( & * block) as * const _;
3626
+ let ptr = unsafe { _Block_copy( ptr as * const #void) } ;
3627
+
3628
+ ptr as * const :: block:: Block <A , R >
3629
+ }
3630
+
3631
+ extern "C" {
3632
+ pub fn _Block_copy( block: * const #void) -> * mut #void;
3633
+ }
3634
+ } ;
3635
+
3636
+ let items = vec ! [ use_block, def_block] ;
3637
+ let old_items = mem:: replace ( result, items) ;
3638
+ result. extend ( old_items. into_iter ( ) ) ;
3639
+ }
3640
+
3563
3641
pub fn prepend_union_types (
3564
3642
ctx : & BindgenContext ,
3565
3643
result : & mut Vec < quote:: Tokens > ,
@@ -3871,4 +3949,48 @@ mod utils {
3871
3949
3872
3950
args
3873
3951
}
3952
+
3953
+ pub fn fnsig_block (
3954
+ ctx : & BindgenContext ,
3955
+ sig : & FunctionSig ,
3956
+ ) -> quote:: Tokens {
3957
+ use super :: ToPtr ;
3958
+
3959
+ let args = sig. argument_types ( ) . iter ( ) . map ( |& ( _, ty) | {
3960
+ let arg_item = ctx. resolve_item ( ty) ;
3961
+ let arg_ty = arg_item. kind ( ) . expect_type ( ) ;
3962
+
3963
+ match * arg_ty. canonical_type ( ctx) . kind ( ) {
3964
+ TypeKind :: Array ( t, _) => {
3965
+ t. to_rust_ty_or_opaque ( ctx, & ( ) )
3966
+ . to_ptr ( ctx. resolve_type ( t) . is_const ( ) )
3967
+ } ,
3968
+ TypeKind :: Pointer ( inner) => {
3969
+ let inner = ctx. resolve_item ( inner) ;
3970
+ let inner_ty = inner. expect_type ( ) ;
3971
+ if let TypeKind :: ObjCInterface ( _) = * inner_ty. canonical_type ( ctx) . kind ( ) {
3972
+ quote ! {
3973
+ id
3974
+ }
3975
+ } else {
3976
+ arg_item. to_rust_ty_or_opaque ( ctx, & ( ) )
3977
+ }
3978
+ } ,
3979
+ _ => {
3980
+ arg_item. to_rust_ty_or_opaque ( ctx, & ( ) )
3981
+ }
3982
+ }
3983
+ } ) ;
3984
+
3985
+ let return_item = ctx. resolve_item ( sig. return_type ( ) ) ;
3986
+ let ret_ty = if let TypeKind :: Void = * return_item. kind ( ) . expect_type ( ) . kind ( ) {
3987
+ quote ! { ( ) }
3988
+ } else {
3989
+ return_item. to_rust_ty_or_opaque ( ctx, & ( ) )
3990
+ } ;
3991
+
3992
+ quote ! {
3993
+ * const :: block:: Block <( #( #args) , * ) , #ret_ty>
3994
+ }
3995
+ }
3874
3996
}
0 commit comments