Thanks for the explanation, it starts to make sense to me now. But when I
change the return type of the first call from "void*" to ICUEnumerationNB I
end up here:

NBExternalStructureType>>coerceReturn: gen

" ... should we support handling return of external structures? "
self error: 'returning pointer to structure?'

The problem is not so urgent for me anymore because I can work around it
using just NBExternalAddress instances. But off course I'm still curious to
know what's the best way to handle these kind of native calls.

Jan.

PS: The code is in http://www.squeaksource.com/ICU.html  ICUCalendarNB>>#
nbTestAllTimeZones




On Fri, Feb 24, 2012 at 2:35 PM, Igor Stasenko <[email protected]> wrote:

> On 24 February 2012 12:10, Jan van de Sandt <[email protected]> wrote:
> > Hi,
> >
> > Well, it works if I don't use the ICUEnumeration class. The first call
> > returns an NBExternalAddress instance. If I pass this instance to the
> second
> > call than it works fine. The native call looks like this:
> >
> > self nbCall: #( char* uenum_next_48(void* aHandle, nil, ICUErrorCodeNB*
> > anErrorCode ) )
> >
> > My idea was to use a subclass of NBExternalHandle where I can put all the
> > functions related to this handle. But it stops working when I copy the
> value
> > from the ExternalAddress to my handle subclass ICUEnumerationNB and use
> one
> > of these calls:
> >
> > self nbCall: #( char* uenum_next_48(ICUEnumerationNB* aHandle, nil,
> > ICUErrorCodeNB* anErrorCode ) )
> >
> > or
> >
> > self nbCall: #( char* uenum_next_48(ICUEnumerationNB aHandle, nil,
> > ICUErrorCodeNB* anErrorCode ) )
> >
>
> Since NBExternalHandle is variable byte class,
> if you pass a pointer to it, like
> ICUEnumerationNB* then FFI will push a pointer to the first indexable
> byte in ICUEnumerationNB instance,
> but not the value of handle stored in this instance.
> In your case, you stored UEnumeration*, but then you pushing
> UEnumeration**, while function expects UEnumeration*.
>
> It is hard to say, why "ICUEnumerationNB aHandle" doesn't works for
> you without looking at code, especially
> that NBExternalAddress is a subclass of NBExternalHandle.
>
> You can try the following:
>
> Since both functions working with same type (UEnumeration*) ,  you can
> actually treat it as if you would have
>
> typedef UEnumeration* ICUEnumerationNB;
> in C.
>
> So, then just remove '*' everywhere (in function which returns it, and
> in functions where you passing it as argument):
>
> self nbCall: #( ICUEnumerationNB ucal_openTimeZones_48(
> ICUErrorCodeNB* anErrorCode ) )
>
> and:
> self nbCall: #( char* uenum_next_48(ICUEnumerationNB aHandle, nil,
> ICUErrorCodeNB* anErrorCode ) )
>
> that should work fine, unless that library doing something strange
> (which also might be the case ;).
>
> P.S. originally, i intentionally raising an error when you passing a
> pointer to NBExternalAddress or Handle types
> (so is allows to pass a just a value, but not a pointer to the value)
> to prevent mistakes like that.
> But some functions actually wanting to get a pointer to the pointer
> (like int** etc), so then they can store a pointer at that pointer,
> and i was added that, because it is convenient.
>
> P.P.S Yo dawg, i put a pointer to that pointer so you can point to
> what it points ;)
>
> --
> Best regards,
> Igor Stasenko.
>
>

Reply via email to