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. > >> > >> > >> 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
