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.
