<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Apr 4, 2019 at 11:43 AM Eliot Miranda <<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">Hi Holger,<br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Apr 4, 2019 at 10:04 AM Holger Freyther <<a href="mailto:holger@freyther.de" target="_blank">holger@freyther.de</a>> wrote:</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">
<br>
> On 3. Apr 2019, at 23:50, Eliot Miranda <<a href="mailto:eliot.miranda@gmail.com" target="_blank">eliot.miranda@gmail.com</a>> wrote:<br>
> <br>
> Hi Holger,<br>
<br>
> It's represented as FFIExternalStructure subclass: #CXCursor. In the case of the callback the handle is an instance of FFIExternalStructureReferenceHandle with an Alien embedded into it.<br>
> <br>
> What is the C signature of the callback function, and what is the source of the marshaling method in the relevant Callback subclass's signatures protocol?<br>
> Also, what's the callout's signature and what is the Smalltalk code for the call?<br>
<br>
<br>
C declaration:<br>
<br>
typedef enum CXChildVisitResult(* CXCursorVisitor) (CXCursor cursor, CXCursor parent, CXClientData client_data);<br>
<br>
and passed to the c function below.<br>
<br>
unsigned clang_visitChildren    (CXCursor parent, CXCursorVisitor visitor,  CXClientData client_data );<br>
<br>
<br>
Smalltalk Source:<br>
<br>
        acceptCallbackFn := <br>
           FFICallback<br>
                signature:  #( CXChildVisitResult (<br>
                                                                CXCursor cursor, <br>
                                                                CXCursor parent, <br>
                                                                CXString client_data))<br></blockquote><div><br></div><div>somewhere in the Callback hierarchy there should me a marshaling method for the platform you're on that matches that signature.  Fo example, in Squeak if I'm calling, say, sort, then there's a callback such as</div><div><br></div><div><span style="white-space:pre-wrap">                </span>Callback</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">                       </span>signature:  #(int (*)(const void *, const void *))</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">                    </span>block: [ :arg1 :arg2 | ((arg1 doubleAt: 1) - (arg2 doubleAt: 1)) sign].</div><div><br></div><div>to marshal the callback's incoming arguments each platform needs a suitable marshaling method that the Callback machinery matches to the signature.  Here they are from Squeak:</div><div><br></div><div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">        </span>Callback methods for signatures</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">        </span>voidstarvoidstarRetint: callbackContext regs: regsAlien</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">                </span><signature: #(int (*)(const void *, const void *))></div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">              </span>self subclassResponsibility</div><div><br></div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">   </span>CallbackForARM32 methods for signatures</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">        </span>voidstarvoidstarRetint: callbackContext regs: regsAlien</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">                </span><signature: #(int (*)(const void *, const void *))></div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">              </span>^callbackContext wordResult:</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">                   </span>(block</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">                         </span>value: (Alien forPointer: (regsAlien unsignedLongAt: 1))</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">                               </span>value: (Alien forPointer: (regsAlien unsignedLongAt: 5)))</div><div><br></div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">     </span>CallbackForWin64X64 methods for signatures</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">     </span>voidstarvoidstarRetint: callbackContext regs: regsAlien</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">                </span><signature: #(int (*)(const void *, const void *))></div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">              </span>^callbackContext wordResult:</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">                   </span>(block</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">                         </span>value: (Alien forPointer: (regsAlien unsignedLongLongAt: 1))</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">                           </span>value: (Alien forPointer: (regsAlien unsignedLongLongAt: 9)))</div><div><br></div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap"> </span>CallbackForX64 methods for signatures</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">  </span>voidstarvoidstarRetint: callbackContext regs: regsAlien</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">                </span><signature: #(int (*)(const void *, const void *))></div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">              </span>^callbackContext wordResult:</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">                   </span>(block</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">                         </span>value: (Alien forPointer: (regsAlien unsignedLongLongAt: 1))</div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">                           </span>value: (Alien forPointer: (regsAlien unsignedLongLongAt: 9)))</div></div></div></div></div></div></div></blockquote><div><br></div><div>Missed one (finger trouble)</div><div><br></div><div><span class="gmail-m_3874790475876866737gmail-Apple-tab-span" style="white-space:pre-wrap">   </span>CallbackForIA32 methods for signatures<br></div><div><span class="gmail-Apple-tab-span" style="white-space:pre">       </span>voidstarvoidstarRetint: callbackContext sp: spAlien</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">            </span><signature: #(int (*)(const void *, const void *))></div><div><span class="gmail-Apple-tab-span" style="white-space:pre">              </span>^callbackContext wordResult:</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                   </span>(block</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                         </span>value: (Alien forPointer: (spAlien unsignedLongAt: 1))</div><div><span class="gmail-Apple-tab-span" style="white-space:pre">                         </span>value: (Alien forPointer: (spAlien unsignedLongAt: 5)))</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div class="gmail_quote"><div><br></div><div>What are is method for your platform?</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">CXChildVisitResult is an enum, CXCursor/CXString are FFIExternalStructure subclasses.<br>
<br>
<br>
<br>
Smalltalk code:<br>
<br>
<br>
        Libclang clang_visitChildren__parentCursor: rootCursor <br>
                                   visitorCallback: acceptCallbackFn <br>
                                        clientData: rootClientData.<br>
<br>
>>#clang_visitChildren__parentCursor: parent <br>
                  visitorCallback: visitor <br>
                       clientData: client_data<br>
        ^ self ffiCall: #( uint clang_visitChildren(<br>
                                                                CXCursor parent,<br>
                                                                CXCursorVisitor visitor,<br>
                                                                CXClientData client_data))<br>
<br>
<br>
<br>
> Or do I chase it from the wrong end?<br>
> <br>
> Without the code I can't help, hence my questions above.<br>
<br>
The full code is in Ben's LibclangPractice (<a href="http://smalltalkhub.com/#!/~BenComan/LibclangPractice" rel="noreferrer" target="_blank">http://smalltalkhub.com/#!/~BenComan/LibclangPractice</a>). I have set a breakpoint in LibclangTest>>#visitChildrenCallbackReturning: to look at the cursor variable and call it's methods. I think my  Pharo PR (<a href="https://github.com/pharo-project/pharo/pull/3136/files#diff-8f4b31166c3a817dd8ad1f0518ae633a" rel="noreferrer" target="_blank">https://github.com/pharo-project/pharo/pull/3136/files#diff-8f4b31166c3a817dd8ad1f0518ae633a</a>) is fixing the callback handling in Unified-FFI.<br>
<br>
<br>
I think I have stumbled into three separate bugs and I just noticed that they are Pharo specific. Unified-FFI doesn't seem to exist for Squeak.<br>
<br>
<br>
1st) an Alien ending inside a handle of a FFIExternalStructure sub-instance. I have made a PR for it and I think it is reasonable to turn the Alien into an ExternalAddress early.<br>
<br>
2nd) Pushing a FFIExternalStructure sub-instance with a FFIExternalStructureReferenceHandle in it to the stack doesn't work. Squeak+ThreadedFFIPlugin simply don't know what a FFIExternalStructureReferenceHandle valueOOP is.<br>
<br>
<br>
3rd) Returning a struct from the callback doesn't to work either. That's a UnifiedFFI bug as well:<br>
<br>
In FFICallbackParameterTests>>#testPassingStructureInTheStack <br>
<br>
        | param |<br>
        callback := FFICallback <br>
                signature: #(int (FFITestStructureSmallIntFloatStructure a))<br>
                block: [ :a |<br>
                        self assert: a x equals: 2.0. <br>
                        self assert: a y equals: 3. ..<br>
<br>
change the "int" to "FFITestStructureSmallIntFloatStructure" and the first assertion will fail. The value of "a x" becomes 3. I have not debugged this.<br>
<br>
<br>
I think only 2nd) is relevant to this list. Support for FFIExternalStructureReferenceHandle will add one level of indirection.<br>
<br>
<br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail-m_3874790475876866737gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div></div></div></div></div>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><span style="font-size:small;border-collapse:separate"><div>_,,,^..^,,,_<br></div><div>best, Eliot</div></span></div></div></div></div></div></div>