On 4 May 2012 18:52, Eliot Miranda <[email protected]> wrote:
>
>
> On Fri, May 4, 2012 at 9:44 AM, Igor Stasenko <[email protected]> wrote:
>>
>> 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.
>
>
> add a test for a structs like
>     typedef struct { char a; char b; char c; } threeBytes;
>     typedef struct { short a; short b; short c; } sixBytes;
>
> (and 5 & 7).  You should see on Mac and Windows these are not passed back in
> registers.
>
omg.. what a mess..
so it actually uses for structs with 1, 2, 4 and 8 bytes size...

>>
>> >>
>> >>
>> >> 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,
> Eliot
>



-- 
Best regards,
Igor Stasenko.
typedef struct { char a1; } foo1;

foo1 f1 ()
{
    foo1 bar = { 1 };
    return bar;
}



typedef struct { char a1; char a2; } foo2;

foo2 f2 ()
{
    foo2 bar = { 1 , 2 };
    return bar;
}


typedef struct { char a1; char a2; char a3; } foo3;

foo3 f3 ()
{
    foo3 bar = { 1 , 2 , 3};
    return bar;
}


typedef struct { char a1; char a2; char a3; char a4; } foo4;

foo4 f4 ()
{
    foo4 bar = { 1 , 2 , 3, 4};
    return bar;
}


typedef struct { char a1; char a2; char a3; char a4; char a5; } foo5;

foo5 f5 ()
{
    foo5 bar = { 1 , 2 , 3, 4, 5};
    return bar;
}


typedef struct { char a1; char a2; char a3; char a4; char a5;
    char a6; } foo6;

foo6 f6 ()
{
    foo6 bar = { 1 , 2 , 3, 4, 5, 6};
    return bar;
}

typedef struct { char a1; char a2; char a3; char a4; char a5;
    char a6; char a7; } foo7;

foo7 f7 ()
{
    foo7 bar = { 1 , 2 , 3, 4, 5, 6, 7};
    return bar;
}



typedef struct { char a1; char a2; char a3; char a4; char a5;
    char a6; char a7; char a8; } foo8;

foo8 f8 ()
{
    foo8 bar = { 1 , 2 , 3, 4, 5, 6, 7, 8};
    return bar;
}

Attachment: test.s
Description: Binary data

Reply via email to