Thank you Igor for the new version of NB. I tested it and it works when returning structs. #Luc 2012/5/4 Igor Stasenko <siguctua@gmail.com>
On 4 May 2012 20:27, Nicolas Cellier <nicolas.cellier.aka.nice@gmail.com> wrote:
I found this link quite detailed on the subject, but restricted to C++ (not entirely sure C compiler produces exactly the same...)
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 <siguctua@gmail.com>:
On 4 May 2012 19:18, Nicolas Cellier < nicolas.cellier.aka.nice@gmail.com> wrote:
Yes, on max too
https://developer.apple.com/library/mac/#documentation/developertools/Concep...
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 <siguctua@gmail.com>:
On 4 May 2012 18:37, Eliot Miranda <eliot.miranda@gmail.com> wrote:
On Fri, May 4, 2012 at 6:13 AM, Igor Stasenko <siguctua@gmail.com>
wrote:
On 4 May 2012 10:38, Luc Fabresse <luc.fabresse@gmail.com> 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...
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.