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.