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.

    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...

$ 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.

Reply via email to