Thank you Igor for the new version of NB. I tested it and it works when returning structs.
#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. > >
