[foreign] RFR 8210264: cleanup semantics of function pointer conversion

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Mon Sep 3 10:04:34 UTC 2018

On 01/09/18 04:46, John Rose wrote:
> On Aug 31, 2018, at 9:04 AM, Maurizio Cimadamore 
> <maurizio.cimadamore at oracle.com 
> <mailto:maurizio.cimadamore at oracle.com>> wrote:
>> http://cr.openjdk.java.net/~mcimadamore/panama/8210264/ 
>> <http://cr.openjdk.java.net/%7Emcimadamore/panama/8210264/>
> This is a good cleanup.
> An object is allowed to implement two functional interfaces, and even
> two interfaces which annotated as native callbacks. So it is possible
> that allocateCallback will be presented with an ambiguous input.
> I suggest that Util.findCallback throw an exception in that case,
> instead of returning the first marked FI that that it finds.
> This won't harm correct code but will let us exclude some corner
> cases.
> Another way to slice this is to require a runtime witness as follows:
> <T> Callback<T> allocateCallback(Class<T> funcInt, T funcIntfInstance);
> default <T> Callback<T> allocateCallback(T funcIntfInstance) {
>   return 
> allocateCallback(Utils.findCallback(funcIntfInstance.getClass()), 
> funcIntfInstance);
> }
> I.e., allow explicit specification of which FI we care about but specify
> a sensible default.  The explicit specification has two effects:  First,
> it allows cast-free passing of a lambda, and second it allows the
> approach to scale to non-native FI types (assuming the scope
> has rules for dealing with type conversion).
I thought about the latter a lot. Honestly, I'd prefer an API point such 
as the one you describe - e.g. with an explicit Class type witness. 
That's the first iteration of the API I experimented with - and I found 
one big usability hurdle with that: the need to pass in opaque 
functional interface names generated by jextract. E.g. what you will be 
looking at would be something like:

qsort(... scope.allocateCallback(StdLib$Func23.class, (p1, p2) -> ... ) )

While I agree this makes the API a lot tighter and avoids the need of a 
dynamic lookup which I dislike, I can also imagine that users will be 
pretty annoyed at having to dig an obscure functional interface name 
just to make the API happy.

Now, the approach I put forward is not bullet proof in this regard: if 
javac inference fails (although, after changes brought in by Java SE 8 
that should be quite rare), the user will still have to dig a type 
witness by hand:

scope.<StdLib$23>allocateCallback( (p1, p2) -> ... )

But this would be (i) very rare and (ii) we could mitigate a lot of the 
pain by having jextract generate predictable functional interface names. 
E.g. instead of Func$23, using Function_ptr_ptr would be a lot clearer 
(and would allow reuse on the jextract side).

I don't think trick (ii) is enough to make a client swallow the fact of 
putting in an explicit witness on any callback call - but maybe I'm 
worrying too much about compactness of client code? But maybe you are 
suggesting the witness-accepting 'allocateCallback' not as a 
replacement, but as a complement for the version included in my patch?

> — John

More information about the panama-dev mailing list