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.

Reply via email to