notes on binding C++
Henry Jen
henry.jen at oracle.com
Wed Jan 31 19:04:56 UTC 2018
We had experimented some C++ support, Mikael had being able to make call into C++ for simple case, but as you know, ABI for C++ is not standardized, so this is all experimental and very targeted.
Ultimate fall back mode, to me, is to writing some C code wrapping up what is needed, then jextract can make call into those C function easily without hassle.
We are aware, as you suggested, macro/template/inline support is tricky, and we are exploring possibilities. My take is that eventually we are gonna need hints, either by recognizing some common patterns or developer intervention.
Like Maurizio said, the first phase is to lay out foundation that is solid we can built on, and we like feedbacks to ensure the design won’t prohibit further improvement on support for different languages. We re really focus on fundamentals/primitives allow us to make calls and expressive primitive types, others features should be able to build on top of that without any issue.
Cheers,
Henry
> On Jan 30, 2018, at 11:05 PM, Samuel Audet <samuel.audet at gmail.com> wrote:
>
> So that's what UpcallHandler is for, good to know! Yes, this is neat. It's basically libffi on steroids. It would be nice to have this documented somewhere.
>
> Now, I will eventually figure out something that is not supported by jextract to make my point :) What about function-like macros? How are those supported? We basically have the same problem with C++ templates: We need a C/C++ compiler to compile them and the compiler needed by the library the user wants to use might not be Clang. And as I pointed out previously, although Clang usually emulates GCC pretty well, it does not work so well in the case of Visual Studio:
> https://clang.llvm.org/docs/MSVCCompatibility.html
> No mention of MSVC 2017! And we're 2018 already...
>
> When I mean "abandon" I mean abandon the current effort to support C++ with jextract because the specs will have been frozen in stone, unable to make accommodations for C++.
>
> How about this, how about we include in jextract a "fallback mode" that basically does what JavaCPP does, and uses JNI along with a C/C++ compiler provided by the user? I mean, it is possible to come up with a whole new C++ runtime, which can instantiate templates for a number of other C++ runtimes (basically figuring out how to do what Clang itself is not even able to do), but do we care? For example, very few people care about features like virtual inheritance, but they are there, and they are required to use some C++ libraries. Since virtual inheritance, for example, is an inefficient feature of the C++ language, it is not something developers use for performance sensitive calls. We could let the C++ compiler figure itself out and we make the call with JNI, until someone complains that this is "slow", but in my opinion that moment will not arrive because it is an inherently inefficient call. The call gets made, it works, that's all that matters, for now.
>
> With a fallback mode in place in the specs, we (the community) could then comfortably be reassured that jextract can be extended with JNI --because we know that that works--whenever required. Why not do it?
>
> Samuel
>
> On 01/31/2018 06:32 AM, Maurizio Cimadamore wrote:
>> On 30/01/18 11:59, Samuel Audet wrote:
>>> Yes, performance improvement for C is the priority, and usability for C++ is secondary. But building "more on it" is not going to work in my opinion. It will require a redesign of pretty much everything anyway, so all efforts towards C++ will probably just be abandoned in the end. The message to the community needs to be clearer than that!
>> Well, I think my message was as clear as you're going to get at this point in time; I believe I showed a possible path to use jextract + JVM code snippets to get at complex API points w/o the need of JNI - that to me seems like building more on what we have e.g. having jextract generate not just a bunch of annotated interfaces, but having it also generate some snippets to go with it.
>> After all, we live in a world of limited resources, and we have to decide how to spend them in order to maximize the benefits that developers could get out of this feature; as other language FFI show, there's a pretty big number of use cases that scream for better integration with native libraries, so we're going with that first. But all the info that I posted, and all the previous discusson on the topic should, in my opinion, be sufficient evidence that we're not just going to stop at C and abandon everything else. If we wanted to do just that, we'll probably not even bother with layout descriptions in the first place.
>>>
>>> When I talk about "virtual inheritance", for example, I talk about "callbacks". So this isn't an issue related to only C++. For the sake of the argument, how are function pointers that call back into a Java method implemented with jextract? My impression is that they use JNI. If they do not, I would be curious to know how this is achieved!
>> I'm not an expert of this part of the code (yet), but my understanding is that there's no JNI involved; when a native library is called with a function pointer a so called UpcallHandler [1] is created - this is a thin wrapper around a method handle (the functional interface method to be called), a unique ID and an UpcallStub; the stub is created from Hotspot code [2] and is essentially a code snippet that performs an upcall back to the Java code (e.g. it calls UpcallHandler::invoke with the right ID). Then, when the argument list is processed ahead of a native call [3], functional interfaces arguments are turned into pointers to such stubs, and the invocation can then proceed normally. This allows to pass e.g. a lambda expression or a method reference where a function pointer was required by the native function, which is rather neat.
>> Maurizio
>> [1] - http://hg.openjdk.java.net/panama/dev/file/127cdae0dede/src/java.base/share/classes/jdk/internal/nicl/UpcallHandler.java [2] - http://hg.openjdk.java.net/panama/dev/file/127cdae0dede/src/hotspot/cpu/x86/nativeInvoker_x86.cpp#l273 [3] - http://hg.openjdk.java.net/panama/dev/file/127cdae0dede/src/java.base/share/classes/jdk/internal/nicl/NativeInvoker.java#l357
>>>
>>> Samuel
>>>
>>> On 01/30/2018 06:33 PM, Maurizio Cimadamore wrote:
>>>> Hi Samuel,
>>>> I'm not aware of any concrete C++ effort right now; as I mentioned to you the goal for now is to get native interop (C) up and running with a stable API - once that's done we can build more on it (and that means getting to C++).
>>>>
>>>> Regarding your question of whether generating stubs is really going to buy us much compared to just use JNI as JavaCPP is doing, I take your point; if you generate an _opaque_ stub and then compile-it with the target compiler, you end up in the same performance ballpark as JavaCPP, I believe, as the invocation cannot be direct and the JIT can't probably see through the stub call.
>>>>
>>>> But I've seen other plans on how to generate those stubs, and such plans include using JVM code snippets (for which there's a branch in the panama repo):
>>>>
>>>> http://mail.openjdk.java.net/pipermail/panama-dev/2016-August/000506.html
>>>>
>>>> A machine code snippet is a piece of assembly (hence platform dependent code) which can be packaged up and exposed to user as a method handle. This means that the JIT can optimize it more or less in the same way as it does for other method handles - meaning that it will now be able to see through the stub call and optimize that, if possible/needed. There are obviously a lot of 'ifs' in this story (the code snippet extension is experimental), but I think it should be clear that, at least on paper, it has the potential to be more efficient than simply generating some C/C++ stub, compiling it, and then calling it opaquely.
>>>>
>>>> You can find some examples of code snippets in this test:
>>>>
>>>> http://hg.openjdk.java.net/panama/dev/file/8437963c6282/test/jdk/panama/snippets/MachineCodeSnippetSamples.java#l51
>>>>
>>>> Maurizio
>>>>
>>>>
>>>> On 30/01/18 08:45, Samuel Audet wrote:
>>>>> On 01/30/2018 02:14 PM, Henry Jen wrote:
>>>>>>
>>>>>>> On Jan 29, 2018, at 8:37 PM, Samuel Audet <samuel.audet at gmail.com> wrote:
>>>>>>>
>>>>>>> BTW, if the C API of libclang exposes all the features we need, it is already possible to use it from Java: https://github.com/bytedeco/javacpp-presets/tree/master/llvm Is jextract in a good enough shape to offer us such an interface to work with and do some dogfooding? If so, it might also be a good place to start a testbed for jextract too. That is exactly what the JavaCPP Presets are: A testbed for JavaCPP. This is what makes JavaCPP actually work with (a few) C++ libraries out there in the wild--unlike SWIG, CppSharp, rust-bindgen, etc. Thoughts?
>>>>>>>
>>>>>>
>>>>>> We have achieved to run jextract on top of libclang binding generated by jextract awhile back, probably need to bring up-to-date with current updates.
>>>>>>
>>>>>> It’s the idea that after this bootstrapping process, we would like to be able open up other capability provided by libclang, also this dogfooding would server as a validation to our approach is working.
>>>>>>
>>>>>
>>>>> Ok, cool! Has anyone tried with the C++ API of Clang since then? Now that sounds like awesome dogfooding to me. And if we can get that wrapped, we're probably not going to have much of any issues with other C++ libraries out there, and I will happily retire JavaCPP. :)
>>>>>
>>>>> Samuel
>>>>
>>>
>
More information about the panama-dev
mailing list