Hi Ben,

On Tue, Sep 27, 2016 at 8:40 AM, Ben Coman <btc@openinworld.com> wrote:
First, my C is a bit rusty so a question about semantics...

�� int * a;
�� typedef int * MyInt;
�� MyInt b;

So obviously the type of 'a' is a pointer,
but is the type of 'b' a pointer?
My intuition is that its not, since the pointer is wrapped inside the type.

Yes it is.�� MyInt (a bad name) is a type that is a pointer to an int.�� So something of type MyInt is of type pointer to int.
��
Now in my UFFI tutorial
http://blog.openinworld.com/2016/09/pharo-libclang-ffi-part-4-ast-walking-with-visitors-callbacks/
I have a callback that I've modified here adding the #inspect...

�� �� acceptCallbackFn :=
�� �� ��FFICallback
�� �� �� �� signature:�� #( CXChildVisitResult (
�� �� �� �� �� �� �� �� �� �� �� �� �� �� �� �� �� �� ��CXCursor cursor,
�� �� �� �� �� �� �� �� �� �� �� �� �� �� �� �� �� �� ��CXCursor parent,
�� �� �� �� �� �� �� �� �� �� �� �� �� �� �� �� �� �� ��CXClientData client_data))
�� �� �� �� block: [ :cursor :parent :clientData |
�� �� �� �� �� �� client_data inspect.
�� �� �� �� �� ��visitResult add: cursor kind item.
�� �� �� �� �� �� aCXChildVisitResult value "@1" ].

This can be invoked by running #testVisitChildrenCallbackBreak
and an inspector opens on an ExternalAddress instead of
the expected CXClientData.

�� �� FFIExternalObject subclass: #CXClientData
�� �� �� �� instanceVariableNames: ''
�� �� �� �� classVariableNames: ''
�� �� �� �� package: 'Libclang'

where the FFIExternalObject says...
"A typical usage of me is to create a subclass, and then use that
subclass name directly in function signatures ... By putting
FFIExternalObject subclass ... as a return type into the function
signature, we are telling the code generator to ***automatically***
convert the return value into an instance of a given class and
initialize its handle to the value returned by the function."


This decision to return ExternalAddress instead of CXClientData
occurs here...
�� FFIExternalObjectType(FFIExternalType)>>handle: aHandle at: index
�� �� �� ��self isPointer ifTrue: [ ^ aHandle pointerAt: index ].
�� �� �� ��^ self basicHandle: aHandle at: index

since...
�� FFIExternalType>>isPointer
�� �� �� ^ self pointerArity > 0

and...
�� FFIExternalObjectType(FFIExternalReferenceType)>>naturalPointerArity
�� �� �� ^ 1

So this naturalPointerArity=1 represents the situation presented with
the C code at the top.�� So should #isPointer consider only the
absolute pointerArity, or should is be...

�� FFIExternalType>>isPointer
�� �� �� ^ self pointerArity > self class naturalPointerArity

Indeed, if I do that, plus these two additions copied from
FFIExternalStructure...

�� FFIExternalReferenceType>>basicHandle: aHandle at: index
�� �� �� ^ self objectClass fromHandle: aHandle.

�� FFIExternalReference>>fromHandle: aHandle
�� �� �� ^self basicNew setHandle: aHandle

Now running #testVisitChildrenCallbackBreak
opens an inspector opens on a CXClientData as expected.
And all UFFI tests continue to run fine.


One thing I found strange though was...
�� FFIExternalStructureType>>naturalPointerArity
�� �� �� ^ 1

I would have thought a struct's natural pointer arity was 0 ?

wdyt?
cheers -ben

This makes my brain hurt.�� A pointer is a pointer, whether it points to a pointer or a datum.�� Hence I find the "self pointerArity > self class naturalPointerArity" approach confusing.
��
_,,,^..^,,,_
best,��Eliot