On 7 May 2012 08:41, Luc Fabresse <[email protected]> wrote:
> Thank you Igor for the new version of NB.
> I tested it and it works when returning structs.
>

!! perfect !! :)


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



-- 
Best regards,
Igor Stasenko.

Reply via email to