Thank you Igor for the new version of NB.
I tested it and it works when returning structs.

#Luc


2012/5/4 Igor Stasenko <[email protected]>

> On 4 May 2012 20:27, Nicolas Cellier <[email protected]>
> wrote:
> > I found this link quite detailed on the subject, but restricted to C++
> > (not entirely sure C compiler produces exactly the same...)
> >
> > http://www.shell-storm.org/papers/files/657.pdf
> >
> thanks for the link, nicolas.. the information about these conventions
> are really sparse.
>
> > See table 7 for the case of returning objects...
> >
> > See also stack cleanup by, 32 bit gcc use hybrid method for structure
> > passed by values thru a pointer...
> >
> > Nicolas
> >
> > 2012/5/4 Igor Stasenko <[email protected]>:
> >> On 4 May 2012 19:18, Nicolas Cellier <
> [email protected]> wrote:
> >>> Yes, on max too
> >>>
> https://developer.apple.com/library/mac/#documentation/developertools/Conceptual/LowLevelABI/130-IA-32_Function_Calling_Conventions/IA32.html
> >>>
> >>> Structures. The called function returns structures according to their
> >>> aligned size.
> >>>
> >>>    Structures 1 or 2 bytes in size are placed in EAX.
> >>>
> >>>    Structures 4 or 8 bytes in size are placed in: EAX and EDX.
> >>>
> >>
> >> okay.. i fixed it in  NativeBoost-Core-IgorStasenko.58
> >>
> >>>    Structures of other sizes are placed at the address supplied by
> >>> the caller. For example, the C++ language occasionally forces the
> >>> compiler to return a value in memory when it would normally be
> >>> returned in registers. See “Passing Arguments” for more information.
> >>>
> >>> I wonder if a structure of size 3 bytes can exist or is automatically
> >>> extended on 4 bytes...
> >>>
> >> yes.. struct alignment is what i fear of..
> >> IMO it is actually silly to not return struct in registers if it less
> >> than 8 bytes
> >> but not power of 2..
> >>
> >> sounds like an artefact of establishing the standards :)
> >>
> >>> $ cat > test_call.c <<END
> >>>
> >>> #include <stdio.h>
> >>> typedef struct { char a,b,c; } abc;
> >>> int main() {
> >>>    abc x;
> >>>    printf("sizeof(abc)=%d\n",sizeof x);
> >>>    return 0;
> >>> }
> >>> END
> >>>
> >>> $ gcc test_call.c
> >>> $ ./a.exe
> >>> sizeof(abc)=3
> >>>
> >>> And what would be the calling conventions of cygwin gcc ?
> >>>
> >>> $ cat > test_call.c <<END
> >>>
> >>> #include <stdio.h>
> >>> typedef struct { char a,b,c; } abc;
> >>> abc sub() {
> >>>   abc result;
> >>>   result.a='a';
> >>>   result.b='b';
> >>>   result.c='c';
> >>>   return result;
> >>> }
> >>> int main() {
> >>>    abc x=sub();
> >>>    printf("sizeof(abc)=%d abc.a=$c\n",sizeof x,x.a);
> >>>    return 0;
> >>> }
> >>> END
> >>>
> >>> $ gcc test_call.c
> >>> $ ./a.exe
> >>> sizeof(abc)=3 abc.a=a
> >>>
> >>> $ gcc -S test_call.c
> >>> $ cat test_call.S
> >>>
> >>>        .file   "test_call.c"
> >>>        .text
> >>> .globl _sub
> >>>        .def    _sub;   .scl    2;      .type   32;     .endef
> >>> _sub:
> >>>        pushl   %ebp
> >>>        movl    %esp, %ebp
> >>>        subl    $16, %esp
> >>>        movl    8(%ebp), %eax
> >>>        movb    $97, -3(%ebp)
> >>>        movb    $98, -2(%ebp)
> >>>        movb    $99, -1(%ebp)
> >>>        movzwl  -3(%ebp), %edx
> >>>        movw    %dx, (%eax)
> >>>        movzbl  -1(%ebp), %edx
> >>>        movb    %dl, 2(%eax)
> >>>        leave
> >>>        ret     $4
> >>>        .def    ___main;        .scl    2;      .type   32;     .endef
> >>>        .section .rdata,"dr"
> >>> LC0:
> >>>        .ascii "sizeof(abc)=%d\12\0"
> >>>        .text
> >>> .globl _main
> >>>        .def    _main;  .scl    2;      .type   32;     .endef
> >>> _main:
> >>>        leal    4(%esp), %ecx
> >>>        andl    $-16, %esp
> >>>        pushl   -4(%ecx)
> >>>        pushl   %ebp
> >>>        movl    %esp, %ebp
> >>>        pushl   %ecx
> >>>        subl    $36, %esp
> >>>        call    ___main
> >>>        leal    -11(%ebp), %eax
> >>>        movl    %eax, (%esp)
> >>>        call    _sub
> >>>        subl    $4, %esp
> >>>        movl    $3, 4(%esp)
> >>>        movl    $LC0, (%esp)
> >>>        call    _printf
> >>>        movl    $0, %eax
> >>>        movl    -4(%ebp), %ecx
> >>>        leave
> >>>        leal    -4(%ecx), %esp
> >>>        ret
> >>>        .def    _printf;        .scl    2;      .type   32;     .endef
> >>>
> >>> But of course, you already were faster than me...
> >>>
> >>> Nicolas
> >>>
> >>> 2012/5/4 Igor Stasenko <[email protected]>:
> >>>> On 4 May 2012 18:37, Eliot Miranda <[email protected]> wrote:
> >>>>>
> >>>>>
> >>>>> On Fri, May 4, 2012 at 6:13 AM, Igor Stasenko <[email protected]>
> wrote:
> >>>>>>
> >>>>>> On 4 May 2012 10:38, Luc Fabresse <[email protected]> wrote:
> >>>>>> > Hi Igor,
> >>>>>> >
> >>>>>> >>
> >>>>>> >> there is a workaround.
> >>>>>> >> all structs in C is returned via pointer.
> >>>>>> >> so, actually a true return type of a function is CvSize*
> >>>>>> >
> >>>>>> >
> >>>>>> > I agree that usually structs are returned through pointers.
> >>>>>> > But here it is not the case.
> >>>>>> >
> >>>>>> > I want to wrap this function:
> >>>>>> > CvSize cvGetSize( const CvArr* arr );
> >>>>>> >
> >>>>>> > and the CvSize struct is returned by value. Am I wrong?
> >>>>>> >
> >>>>>>
> >>>>>> i don't know.. this is a bit shady part of C ABI.
> >>>>>> Some compilers use return-by-value, some return by pointer
> >>>>>> by forcing a caller to pass a hidden implicit argument as a pointer
> to
> >>>>>> the struct, which then filled with values by
> >>>>>> the function you call.
> >>>>>
> >>>>>
> >>>>> IIRC x86 ABIs (all the ones I encountered at least, windows, mac,
> linux,
> >>>>> solaris)  support structure return (by-value structure return) by
> passing a
> >>>>> hidden first argument which is a pointer to a structure into which
> to copy
> >>>>> the result.  The callee copies the result back through this pointer.
> >>>>>
> >>>>> Where these ABIs differ is in returning small structures.  On win32
> >>>>> structures a power-of-two in size of 8 bytes or less are returned in
> >>>>> EAX:EDX.  IIRC on linux and mac all structures are returned through
> the
> >>>>> hidden first argument pointer.  See
> >>>>> ThreadedIA32FFIPlugin>>returnStructInRegisters:
> >>>>>
> >>>> on macs (at least what gcc generates) it also returns structs <=8
> >>>> bytes size in registers:
> >>>>
> >>>>
> >>>> so , currently i implemented it like that:
> >>>> if sizeof(struct) <= 8 then i assume function returns it in EAX: EDX
> >>>> otherwise via hidden pointer.
> >>>>
> >>>>>>
> >>>>>>
> >>>>>> It is easy to add support for that, but to make it work correctly
> can
> >>>>>> be tricky.
> >>>>>> See this, for example:
> >>>>>>
> >>>>>>
> http://stackoverflow.com/questions/161788/are-there-any-downsides-to-passing-structs-by-value-in-c-rather-than-passing-a
> >>>>>>
> >>>>>>
> >>>>>> >>
> >>>>>> >>
> >>>>>> >> so, what you do is to change the return value to simple void*
> >>>>>> >> and then copy the contents of struct into instance of
> corresponding
> >>>>>> >> NBExternalStructure subclass
> >>>>>> >> using #fromPointer: method.. to conveniently access its fields
> values.
> >>>>>> >
> >>>>>> >
> >>>>>> > yes I saw that in NB tests.
> >>>>>> >
> >>>>>> >>
> >>>>>> >>
> >>>>>> >>
> >>>>>> >> but this is in general, in your case this function is actually
> inlined
> >>>>>> >> by compiler (as CV_INLINE suggests), so there could be even no
> >>>>>> >> exported symbol for it in dynamic library.
> >>>>>> >> and the function is actually so simple, that you don't need to
> wrap it
> >>>>>> >> at
> >>>>>> >> all.
> >>>>>> >> you can just create a subclass of NBExternalStructure , named
> CvSize,
> >>>>>> >> implement fieldDesc method as:
> >>>>>> >>
> >>>>>> >> fieldsDesc
> >>>>>> >> ^ #(
> >>>>>> >> int width;
> >>>>>> >> int height
> >>>>>> >> )
> >>>>>> >>
> >>>>>> >>
> >>>>>> >> and if you invoke:
> >>>>>> >>
> >>>>>> >> CvSize new width: 1 height:2
> >>>>>> >>
> >>>>>> >> it will be equivalent as if you will call cvSize(1,2) function.
> >>>>>> >
> >>>>>> >
> >>>>>> > yes it is exactly what I did.
> >>>>>> >
> >>>>>> > So my problem is:
> >>>>>> >
> >>>>>> > NBCvSize implemented as a subclass of NBExternalStruct with
> fieldDesc
> >>>>>> > correctly set up.
> >>>>>> > Then wrap the function cvGetSize:
> >>>>>> >
> >>>>>> > getSize
> >>>>>> >       self nbCall: #(NBCvSize cvGetSize(IplImage self)) module:
> LIB_CV.
> >>>>>> >
> >>>>>> > But I get a debugger because:
> >>>>>> >
> >>>>>> > NBExternalStruct>>coerceReturn: gen
> >>>>>> > " ... should we support handling return of external structures? "
> >>>>>> > self error: 'returning pointer to structure?'
> >>>>>> >
> >>>>>> > And I have no idea how to implement this (black magic EAX pop
> push ;-))
> >>>>>> > to
> >>>>>> > coerce result of struct.
> >>>>>> >
> >>>>>>
> >>>>>>
> >>>>>> you don't. if function takes an implicit struct pointer, you can
> just
> >>>>>> rewrite the function signature from
> >>>>>> NBCvSize cvGetSize(IplImage self)
> >>>>>> to:
> >>>>>>
> >>>>>> void cvGetSize(NBCvSize hidden, IplImage self)
> >>>>>>
> >>>>>> and so, you pass a fresh instance of NBCvSize as argument, which
> >>>>>> function then fill.
> >>>>>> But if C compiler using registers to return struct.. then you're
> screwed
> >>>>>> :)
> >>>>>>
> >>>>>> Anyways, Luc i will try to read docs about C ABI and see if we can
> >>>>>> easily add support for that.
> >>>>>>
> >>>>>> --
> >>>>>> Best regards,
> >>>>>> Igor Stasenko.
> >>>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>> --
> >>>>> best,
> >>>>> Eliot
> >>>>>
> >>>>
> >>>>
> >>>>
> >>>> --
> >>>> Best regards,
> >>>> Igor Stasenko.
> >>>
> >>
> >>
> >>
> >> --
> >> Best regards,
> >> Igor Stasenko.
> >>
> >
>
>
>
> --
> Best regards,
> Igor Stasenko.
>
>

Reply via email to