@@ -296,19 +296,20 @@ end
296296
297297# ############################## Struct ###############################
298298
299- function _emit_getproperty_ptr ! (body, root_cursor, cursor, options)
299+ function _emit_pointer_access ! (body, root_cursor, cursor, options)
300300 field_cursors = fields (getCursorType (cursor))
301301 field_cursors = isempty (field_cursors) ? children (cursor) : field_cursors
302302 for field_cursor in field_cursors
303303 n = name (field_cursor)
304304 if isempty (n)
305- _emit_getproperty_ptr ! (body, root_cursor, field_cursor, options)
305+ _emit_pointer_access ! (body, root_cursor, field_cursor, options)
306306 continue
307307 end
308308 fsym = make_symbol_safe (n)
309309 fty = getCursorType (field_cursor)
310310 ty = translate (tojulia (fty), options)
311311 offset = getOffsetOf (getCursorType (root_cursor), n)
312+
312313 if isBitField (field_cursor)
313314 w = getFieldDeclBitWidth (field_cursor)
314315 @assert w <= 32 # Bit fields should not be larger than int(32 bits)
@@ -322,12 +323,63 @@ function _emit_getproperty_ptr!(body, root_cursor, cursor, options)
322323 end
323324end
324325
325- # Base.getproperty(x::Ptr, f::Symbol) -> Ptr
326+ # getptr(x::Ptr, f::Symbol) -> Ptr
327+ function emit_getptr! (dag, node, options)
328+ sym = make_symbol_safe (node. id)
329+ signature = Expr (:call , :getptr , :(x:: Ptr{$sym} ), :(f:: Symbol ))
330+ body = Expr (:block )
331+ _emit_pointer_access! (body, node. cursor, node. cursor, options)
332+
333+ push! (body. args, :(error ($ (" Unrecognized field of type `$sym `" ) * " : $f " )))
334+ push! (node. exprs, Expr (:function , signature, body))
335+ return dag
336+ end
337+
338+ function emit_deref_getproperty! (body, root_cursor, cursor, options)
339+ field_cursors = fields (getCursorType (cursor))
340+ field_cursors = isempty (field_cursors) ? children (cursor) : field_cursors
341+ for field_cursor in field_cursors
342+ n = name (field_cursor)
343+ if isempty (n)
344+ emit_deref_getproperty! (body, root_cursor, field_cursor, options)
345+ continue
346+ end
347+ fsym = make_symbol_safe (n)
348+ fty = getCursorType (field_cursor)
349+ canonical_type = getCanonicalType (fty)
350+
351+ return_expr = :(getptr (x, f))
352+
353+ # Automatically dereference all field types except for nested structs
354+ # and arrays.
355+ if ! (canonical_type isa Union{CLRecord, CLConstantArray}) && ! isBitField (field_cursor)
356+ return_expr = :(unsafe_load ($ return_expr))
357+ elseif isBitField (field_cursor)
358+ return_expr = :(getbitfieldproperty (x, $ return_expr))
359+ end
360+
361+ ex = :(f === $ (QuoteNode (fsym)) && return $ return_expr)
362+ push! (body. args, ex)
363+ end
364+ end
365+
366+ # Base.getproperty(x::Ptr, f::Symbol)
326367function emit_getproperty_ptr! (dag, node, options)
368+ auto_deref = get (options, " auto_field_dereference" , false )
327369 sym = make_symbol_safe (node. id)
370+
371+ # If automatically dereferencing, we first need to emit getptr!()
372+ if auto_deref
373+ emit_getptr! (dag, node, options)
374+ end
375+
328376 signature = Expr (:call , :(Base. getproperty), :(x:: Ptr{$sym} ), :(f:: Symbol ))
329377 body = Expr (:block )
330- _emit_getproperty_ptr! (body, node. cursor, node. cursor, options)
378+ if auto_deref
379+ emit_deref_getproperty! (body, node. cursor, node. cursor, options)
380+ else
381+ _emit_pointer_access! (body, node. cursor, node. cursor, options)
382+ end
331383 push! (body. args, :(return getfield (x, f)))
332384 getproperty_expr = Expr (:function , signature, body)
333385 push! (node. exprs, getproperty_expr)
@@ -370,10 +422,14 @@ end
370422function emit_setproperty! (dag, node, options)
371423 sym = make_symbol_safe (node. id)
372424 signature = Expr (:call , :(Base. setproperty!), :(x:: Ptr{$sym} ), :(f:: Symbol ), :v )
373- store_expr = :(unsafe_store! (getproperty (x, f), v))
425+
426+ auto_deref = get (options, " auto_field_dereference" , false )
427+ pointer_getter = auto_deref ? :getptr : :getproperty
428+ store_expr = :(unsafe_store! ($ pointer_getter (x, f), v))
429+
374430 if is_bitfield_type (node. type)
375431 body = quote
376- fptr = getproperty (x, f)
432+ fptr = $ pointer_getter (x, f)
377433 if fptr isa Ptr
378434 $ store_expr
379435 else
@@ -398,7 +454,7 @@ function get_names_types(root_cursor, cursor, options)
398454 for field_cursor in field_cursors
399455 n = name (field_cursor)
400456 if isempty (n)
401- _emit_getproperty_ptr ! (root_cursor, field_cursor, options)
457+ _emit_pointer_access ! (root_cursor, field_cursor, options)
402458 continue
403459 end
404460 fsym = make_symbol_safe (n)
0 commit comments