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;
}
test.s
Description: Binary data
