@@ -13,6 +13,7 @@ use ir::item::{Item, ItemAncestors, ItemCanonicalName, ItemCanonicalPath};
13
13
use ir:: item_kind:: ItemKind ;
14
14
use ir:: layout:: Layout ;
15
15
use ir:: module:: Module ;
16
+ use ir:: objc:: ObjCInterface ;
16
17
use ir:: ty:: { Type , TypeKind } ;
17
18
use ir:: type_collector:: ItemSet ;
18
19
use ir:: var:: Var ;
@@ -87,6 +88,9 @@ struct CodegenResult<'a> {
87
88
/// Whether an incomplete array has been generated at least once.
88
89
saw_incomplete_array : bool ,
89
90
91
+ /// Whether Objective C types have been seen at least once.
92
+ saw_objc : bool ,
93
+
90
94
items_seen : HashSet < ItemId > ,
91
95
/// The set of generated function/var names, needed because in C/C++ is
92
96
/// legal to do something like:
@@ -119,6 +123,7 @@ impl<'a> CodegenResult<'a> {
119
123
items : vec ! [ ] ,
120
124
saw_union : false ,
121
125
saw_incomplete_array : false ,
126
+ saw_objc : false ,
122
127
codegen_id : codegen_id,
123
128
items_seen : Default :: default ( ) ,
124
129
functions_seen : Default :: default ( ) ,
@@ -140,6 +145,10 @@ impl<'a> CodegenResult<'a> {
140
145
self . saw_incomplete_array = true ;
141
146
}
142
147
148
+ fn saw_objc ( & mut self ) {
149
+ self . saw_objc = true ;
150
+ }
151
+
143
152
fn seen ( & self , item : ItemId ) -> bool {
144
153
self . items_seen . contains ( & item)
145
154
}
@@ -184,6 +193,7 @@ impl<'a> CodegenResult<'a> {
184
193
185
194
self . saw_union |= new. saw_union ;
186
195
self . saw_incomplete_array |= new. saw_incomplete_array ;
196
+ self . saw_objc |= new. saw_objc ;
187
197
188
198
new. items
189
199
}
@@ -359,6 +369,9 @@ impl CodeGenerator for Module {
359
369
if ctx. need_bindegen_complex_type ( ) {
360
370
utils:: prepend_complex_type ( ctx, & mut * result) ;
361
371
}
372
+ if result. saw_objc {
373
+ utils:: prepend_objc_header ( ctx, & mut * result) ;
374
+ }
362
375
}
363
376
} ;
364
377
@@ -623,6 +636,9 @@ impl CodeGenerator for Type {
623
636
TypeKind :: Enum ( ref ei) => {
624
637
ei. codegen ( ctx, result, whitelisted_items, item)
625
638
}
639
+ TypeKind :: ObjCInterface ( ref interface) => {
640
+ interface. codegen ( ctx, result, whitelisted_items, item)
641
+ }
626
642
ref u @ TypeKind :: UnresolvedTypeRef ( ..) => {
627
643
unreachable ! ( "Should have been resolved after parsing {:?}!" , u)
628
644
}
@@ -2111,6 +2127,9 @@ impl ToRustTy for Type {
2111
2127
let ident = ctx. rust_ident ( & name) ;
2112
2128
quote_ty ! ( ctx. ext_cx( ) , $ident)
2113
2129
}
2130
+ TypeKind :: ObjCInterface ( ..) => {
2131
+ quote_ty ! ( ctx. ext_cx( ) , id)
2132
+ } ,
2114
2133
ref u @ TypeKind :: UnresolvedTypeRef ( ..) => {
2115
2134
unreachable ! ( "Should have been resolved after parsing {:?}!" , u)
2116
2135
}
@@ -2144,10 +2163,22 @@ impl ToRustTy for FunctionSig {
2144
2163
// the array type derivation.
2145
2164
//
2146
2165
// [1]: http://c0x.coding-guidelines.com/6.7.5.3.html
2147
- let arg_ty = if let TypeKind :: Array ( t, _) = * arg_ty. canonical_type ( ctx) . kind ( ) {
2148
- t. to_rust_ty ( ctx) . to_ptr ( arg_ty. is_const ( ) , ctx. span ( ) )
2149
- } else {
2150
- arg_item. to_rust_ty ( ctx)
2166
+ let arg_ty = match * arg_ty. canonical_type ( ctx) . kind ( ) {
2167
+ TypeKind :: Array ( t, _) => {
2168
+ t. to_rust_ty ( ctx) . to_ptr ( arg_ty. is_const ( ) , ctx. span ( ) )
2169
+ } ,
2170
+ TypeKind :: Pointer ( inner) => {
2171
+ let inner = ctx. resolve_item ( inner) ;
2172
+ let inner_ty = inner. expect_type ( ) ;
2173
+ if let TypeKind :: ObjCInterface ( _) = * inner_ty. canonical_type ( ctx) . kind ( ) {
2174
+ quote_ty ! ( ctx. ext_cx( ) , id)
2175
+ } else {
2176
+ arg_item. to_rust_ty ( ctx)
2177
+ }
2178
+ } ,
2179
+ _ => {
2180
+ arg_item. to_rust_ty ( ctx)
2181
+ }
2151
2182
} ;
2152
2183
2153
2184
let arg_name = match * name {
@@ -2263,6 +2294,85 @@ impl CodeGenerator for Function {
2263
2294
}
2264
2295
}
2265
2296
2297
+ impl CodeGenerator for ObjCInterface {
2298
+ type Extra = Item ;
2299
+ fn codegen < ' a > ( & self ,
2300
+ ctx : & BindgenContext ,
2301
+ result : & mut CodegenResult < ' a > ,
2302
+ _whitelisted_items : & ItemSet ,
2303
+ _: & Item ) {
2304
+ let mut impl_items = vec ! [ ] ;
2305
+ let mut trait_items = vec ! [ ] ;
2306
+
2307
+ for method in self . methods ( ) {
2308
+ let method_name = ctx. rust_ident ( method. name ( ) ) ;
2309
+
2310
+ let body = quote_stmt ! ( ctx. ext_cx( ) , msg_send![ self , $method_name] )
2311
+ . unwrap ( ) ;
2312
+ let block = ast:: Block {
2313
+ stmts : vec ! [ body] ,
2314
+ id : ast:: DUMMY_NODE_ID ,
2315
+ rules : ast:: BlockCheckMode :: Default ,
2316
+ span : ctx. span ( ) ,
2317
+ } ;
2318
+
2319
+ let sig = aster:: AstBuilder :: new ( )
2320
+ . method_sig ( )
2321
+ . unsafe_ ( )
2322
+ . fn_decl ( )
2323
+ . self_ ( )
2324
+ . build ( ast:: SelfKind :: Value ( ast:: Mutability :: Immutable ) )
2325
+ . build ( ast:: FunctionRetTy :: Default ( ctx. span ( ) ) ) ;
2326
+ let attrs = vec ! [ ] ;
2327
+
2328
+ let impl_item = ast:: ImplItem {
2329
+ id : ast:: DUMMY_NODE_ID ,
2330
+ ident : ctx. rust_ident ( method. rust_name ( ) ) ,
2331
+ vis : ast:: Visibility :: Inherited , // Public,
2332
+ attrs : attrs. clone ( ) ,
2333
+ node : ast:: ImplItemKind :: Method ( sig. clone ( ) , P ( block) ) ,
2334
+ defaultness : ast:: Defaultness :: Final ,
2335
+ span : ctx. span ( ) ,
2336
+ } ;
2337
+
2338
+ let trait_item = ast:: TraitItem {
2339
+ id : ast:: DUMMY_NODE_ID ,
2340
+ ident : ctx. rust_ident ( method. rust_name ( ) ) ,
2341
+ attrs : attrs,
2342
+ node : ast:: TraitItemKind :: Method ( sig, None ) ,
2343
+ span : ctx. span ( ) ,
2344
+ } ;
2345
+
2346
+ impl_items. push ( impl_item) ;
2347
+ trait_items. push ( trait_item)
2348
+ }
2349
+
2350
+
2351
+ let trait_block = aster:: AstBuilder :: new ( )
2352
+ . item ( )
2353
+ . pub_ ( )
2354
+ . trait_ ( self . name ( ) )
2355
+ . with_items ( trait_items)
2356
+ . build ( ) ;
2357
+
2358
+ let ty_for_impl = quote_ty ! ( ctx. ext_cx( ) , id) ;
2359
+ let impl_block = aster:: AstBuilder :: new ( )
2360
+ . item ( )
2361
+ . impl_ ( )
2362
+ . trait_ ( )
2363
+ . id ( self . name ( ) )
2364
+ . build ( )
2365
+ . with_items ( impl_items)
2366
+ . build_ty ( ty_for_impl) ;
2367
+
2368
+ result. push ( trait_block) ;
2369
+ result. push ( impl_block) ;
2370
+ result. saw_objc ( ) ;
2371
+ }
2372
+ }
2373
+
2374
+
2375
+
2266
2376
pub fn codegen ( context : & mut BindgenContext ) -> Vec < P < ast:: Item > > {
2267
2377
context. gen ( |context| {
2268
2378
let counter = Cell :: new ( 0 ) ;
@@ -2296,6 +2406,32 @@ mod utils {
2296
2406
use syntax:: ast;
2297
2407
use syntax:: ptr:: P ;
2298
2408
2409
+
2410
+ pub fn prepend_objc_header ( ctx : & BindgenContext ,
2411
+ result : & mut Vec < P < ast:: Item > > ) {
2412
+ let use_objc = if ctx. options ( ) . objc_extern_crate {
2413
+ quote_item ! ( ctx. ext_cx( ) ,
2414
+ use objc;
2415
+ ) . unwrap ( )
2416
+ } else {
2417
+ quote_item ! ( ctx. ext_cx( ) ,
2418
+ #[ macro_use]
2419
+ extern crate objc;
2420
+ ) . unwrap ( )
2421
+ } ;
2422
+
2423
+
2424
+ let id_type = quote_item ! ( ctx. ext_cx( ) ,
2425
+ #[ allow( non_camel_case_types) ]
2426
+ pub type id = * mut objc:: runtime:: Object ;
2427
+ )
2428
+ . unwrap ( ) ;
2429
+
2430
+ let items = vec ! [ use_objc, id_type] ;
2431
+ let old_items = mem:: replace ( result, items) ;
2432
+ result. extend ( old_items. into_iter ( ) ) ;
2433
+ }
2434
+
2299
2435
pub fn prepend_union_types ( ctx : & BindgenContext ,
2300
2436
result : & mut Vec < P < ast:: Item > > ) {
2301
2437
let prefix = ctx. trait_prefix ( ) ;
0 commit comments