[graalvm-users] [External] : Re: c++ bytecode from java

Darrell Schiebel darrell at schiebel.us
Mon Feb 1 17:39:06 PST 2021


Thanks very much! That resolved the problems for me with executing the
bytecode from java.

Darrell


On Mon, Feb 1, 2021 at 8:33 AM Roland Schatz <roland.schatz at oracle.com>
wrote:

> "--llvm.C++Interop" is an option for the GraalVM LLVM Runtime, not for
> compiler.
>
> You need to pass it to the GraalVM launcher (e.g. lli):
> lli --llvm.C++Interop <bitcode file>
>
> Or if you're embedding it in a Java application, you can pass the option
> to the ContextBuilder:
>
>         Context polyglot = Context.newBuilder()
> 				       .allowExperimentalOptions(true)
> 				       .option("llvm.C++Interop", "true")
>         		               .allowAllAccess(true).build();
>
>
> - Roland
>
> On 1/29/21 7:29 PM, Darrell Schiebel wrote:
>
> Thanks very much for your reply. It was very useful information, but I
> haven't been able to get the "--llvm.C++Interop" flag to be accepted:
>
> bash$ type clang++
>
> clang++ is hashed
> (/Library/Java/JavaVirtualMachines/graalvm-ee-java8-21.0.0/Contents/Home/jre/languages/llvm/native/bin/clang++)
>
> bash$ clang++ -g --llvm.C++Interop -std=c++11 -shared -o methodsTest.so
> methodsTest.cpp -lgraalvm-llvm
>
> clang-10: *error: *unsupported option '--llvm.C++Interop'
>
> clang-10: *error: *unsupported option '--llvm.C++Interop'
>
> bash$
>
>
> So I'm not sure if this is a new flag that has not made it into production
> or if it is an old flag that has been retired.
>
> I appreciate the work that's gone into GraalVM. It will be great if it
> provides a way to integrate legacy systems into a modern ecosystem.
>
> Darrell
>
>
> On Tue, Jan 26, 2021 at 12:50 PM Roland Schatz <roland.schatz at oracle.com>
> wrote:
>
>> Hi,
>>
>> The interop support for C++ is currently work in progress, some things
>> work already, others not yet.
>> Some of the C++ interop features are behind a flag, try passing
>> "--llvm.C++Interop".
>>
>> Calling constructors and non-virtual methods should work already.
>> There is a WIP PR for virtual method calls:
>> https://github.com/oracle/graal/pull/2932
>> <https://urldefense.com/v3/__https://github.com/oracle/graal/pull/2932__;!!GqivPVa7Brio!IwKBSALxE-CiB-oAQ46lEv4ZRCdDpz5VCpAQi9MxhHvSiPMwOx9W02hUi2cQ_AQuCwg$>
>>
>> C++ interop is a very recent feature and doesn't have many users yet, so
>> there might be bugs.
>>
>> Some more comments inline below...
>>
>> On 1/25/21 10:48 PM, Darrell Schiebel wrote:
>>
>> Hello,
>>
>> I'm trying to understand the capabilities and limitations of using C++
>> libraries from Java. One of the more complete examples I could find was the:
>>
>>    -
>>
>>    CxxMethodsTest.java/methodsTest.cpp
>>
>> test from the GraalVM distribution. I removed the unit test framework,
>> but I find that there are some operations which fail (in Java):
>>
>>    1. retrieving a class: testLibrary.getMember("Point")
>>
>> That should already work. You should be able to use to create instances
>> of "Point" (with `point.newInstance(...)`).
>> It might be that this needs the "--llvm.C++Interop" flag though.
>>
>>
>>    1. retrieving a class method: squaredEuclideanDistance =
>>    testLibrary.getMember("squaredEuclideanDistance")
>>
>> That doesn't work since "squaredEuclideanDistance" is not a global
>> function. If you have an instance of "Point", you should be able to
>> `point.getMember("squaredEuclideanDistance")` and execute the result, or
>> just use `point.invokeMember("squaredEuclideanDistance", ...)` to directly
>> invoke methods.
>>
>>
>>    1. invoking a class member: testLibrary.invokeMember("setY", point2,
>>    8)
>>
>> Same thing. This needs to be `point2.invokeMember("setY", 8)`.
>>
>> I am using GraalVM 21.0.0, and I compiled the C++ like:
>>
>>    -
>>
>>    clang++ -std=c++11 -shared -o methodsTest.so methodsTest.cpp
>>    -lgraalvm-llvm
>>
>> I suppose maybe the testing framework may compile the C++ source code
>> differently. Any idea where I've gone astray?
>>
>> Is that "clang++" from the toolchain we ship with GraalVM? If yes, then
>> that's the correct way to build.
>>
>> If no: If you want to use interop (both C++ or C), you need to compile
>> with debug info enabled. Also note that we currently only support libc++
>> (the one from the LLVM project), not libstdc++ (the one from GCC, which is
>> the default on most Linux systems).
>>
>> You can get the path to our toolchain using "lli --print-toolchain-path"
>> (you might have to install it using "gu install llvm-toolchain", it's an
>> optional component since you don't need it at runtime). The "clang++"
>> from there automatically sets the correct flags. You can use "-v" to see
>> what exactly it does.
>>
>>
>> I think they may compile without name mangling or perhaps they compile
>> the cpp file on the fly... I don't know exactly what happens behind the
>> scenes with:
>>
>>    -
>>
>>    testLibrary = loadTestBitcodeValue("methodsTest.cpp")
>>
>> That's just some path manipulation to locate .so file for that test,
>> which is somewhere under mxbuild in a directory called
>> "methodsTest.cpp.dir". It doesn't do any compilation, that is done using mx
>> and make.
>>
>> My modified methodsTest.cpp file is down below.
>>
>> It seems like these are the key points:
>>
>>    - pointers should be used to pass/return objects (no mapping from
>>    List<T> to std::list<T> for example)
>>
>> Correct, currently we don't support by-value arguments in interop (except
>> primitives of course). Everything must be pointers. Not sure about C++
>> references, they should work in principle, since in bitcode they are also
>> just pointers. But I've never tried to be honest.
>>
>>
>>    - mangled names do not work (unless the mangled name is used for
>>    lookup, of course)
>>
>> With the "--llvm.C++Interop" flag that should work. We read the unmangled
>> names from the debug info.
>> This probably only works if there is no name conflict with the unmangled
>> name, i.e. no overloading.
>>
>>
>>    - class based inherited methods work (using an object pointer)
>>    - looking up methods and supplying the object and args does not work
>>    (e.g. squareEuclideanDistance above)
>>    - retrieving object constructor as a function (e.g.
>>    getMember("Point") above)
>>
>> Does this seem right? I've looked at the examples I could find on the
>> GraalVM.org website but are there any bigger examples of Java/C++
>> integration via GraalVM?
>>
>> Since this is a work in progress feature, we don't have any published
>> examples for C++ yet.
>>
>> Most of our users are only using C-based interfaces, even if the actual
>> implementation behind the interface is in C++. That is of course a
>> workaround you can use right now, but not a nice one.
>> We'll probably publish more examples once we reach a more complete state
>> of our C++ interop implementation.
>>
>>
>> As I wrote in the beginning, all of this is pretty new, so not everything
>> might work out of the box. You're welcome to play around with it, and if
>> you get stuck, feel free to ask questions or report issues!
>>
>>
>> - Roland
>>
>>
>> thanks for any advice,
>> Darrell
>>
>> /*
>>  * Copyright (c) 2020, Oracle and/or its affiliates.
>>  *
>>  * All rights reserved.
>>  *
>>  * Redistribution and use in source and binary forms, with or without
>> modification, are
>>  * permitted provided that the following conditions are met:
>>  *
>>  * 1. Redistributions of source code must retain the above copyright
>> notice, this list of
>>  * conditions and the following disclaimer.
>>  *
>>  * 2. Redistributions in binary form must reproduce the above copyright
>> notice, this list of
>>  * conditions and the following disclaimer in the documentation and/or
>> other materials provided
>>  * with the distribution.
>>  *
>>  * 3. Neither the name of the copyright holder nor the names of its
>> contributors may be used to
>>  * endorse or promote products derived from this software without
>> specific prior written
>>  * permission.
>>  *
>>  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
>> "AS IS" AND ANY EXPRESS
>>  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
>> WARRANTIES OF
>>  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
>> IN NO EVENT SHALL THE
>>  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
>> INCIDENTAL, SPECIAL,
>>  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
>> PROCUREMENT OF SUBSTITUTE
>>  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
>> INTERRUPTION) HOWEVER CAUSED
>>  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
>> OR TORT (INCLUDING
>>  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
>> SOFTWARE, EVEN IF ADVISED
>>  * OF THE POSSIBILITY OF SUCH DAMAGE.
>>  */
>> #include <graalvm/llvm/polyglot.h>
>> #include <stdlib.h>
>> #include <math.h>
>>
>> #define EXTERN extern "C"
>>
>> class Point {
>> protected:
>>     int x;
>>     int y;
>>
>> public:
>>     Point();
>>     int getX();
>>     int getY();
>>     void setX(int val);
>>     void setY(int val);
>>     double squaredEuclideanDistance(Point *other);
>> };
>>
>> POLYGLOT_DECLARE_TYPE(Point)
>>
>> class XtendPoint : public Point {
>> private:
>>     int z;
>>
>> public:
>>     XtendPoint();
>>     int getZ();
>>     void setZ(int val);
>>     int getZ(int constant);
>>     int getX();
>> };
>>
>> POLYGLOT_DECLARE_TYPE(XtendPoint)
>>
>> //class methods
>>
>> Point::Point() {
>>     x = 0;
>>     y = 0;
>> }
>>
>> int Point::getX() {
>>     return x;
>> }
>>
>> int Point::getY() {
>>     return y;
>> }
>>
>> void Point::setX(int val) {
>>     x = val;
>> }
>>
>> void Point::setY(int val) {
>>     y = val;
>> }
>>
>> double Point::squaredEuclideanDistance(Point *other) {
>>     double dX = (double) (x - other->x);
>>     double dY = (double) (y - other->y);
>>     return dX * dX + dY * dY;
>> }
>>
>> XtendPoint::XtendPoint() {
>>     z = 0;
>> }
>>
>> int XtendPoint::getZ() {
>>     return z;
>> }
>>
>> void XtendPoint::setZ(int dZ) {
>>     z = dZ;
>> }
>>
>> int XtendPoint::getZ(int constantOffset) {
>>     return z + constantOffset;
>> }
>>
>> int XtendPoint::getX() {
>>     return x * 2;
>> }
>>
>> //functions
>> EXTERN void *allocNativePoint() {
>>     Point *ret = (Point *) malloc(sizeof(*ret));
>>     return polyglot_from_Point(ret);
>> }
>>
>> EXTERN void *allocNativeXtendPoint() {
>>     XtendPoint *ret = (XtendPoint *) malloc(sizeof(*ret));
>>     return polyglot_from_XtendPoint(ret);
>> }
>>
>> EXTERN void swap(Point *p, Point *q) {
>>     Point tmp = *q;
>>     *q = *p;
>>     *p = tmp;
>> }
>>
>> EXTERN void freeNativePoint(Point *p) {
>>     free(p);
>> }
>>
>> EXTERN void freeNativeXtendPoint(XtendPoint *p) {
>>     free(p);
>> }
>>
>>
>> _______________________________________________
>> GraalVM-Users mailing listGraalVM-Users at oss.oracle.comhttps://oss.oracle.com/mailman/listinfo/graalvm-users
>>
>>
>> _______________________________________________
>> GraalVM-Users mailing list
>> GraalVM-Users at oss.oracle.com
>> https://oss.oracle.com/mailman/listinfo/graalvm-users
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://oss.oracle.com/pipermail/graalvm-users/attachments/20210201/ee6b7a75/attachment-0001.html 


More information about the GraalVM-Users mailing list