[graalvm-users] c++ bytecode from java

Darrell Schiebel darrell at schiebel.us
Fri Jan 29 10:29:27 PST 2021


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
>
> 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/20210129/77105032/attachment-0001.html 


More information about the GraalVM-Users mailing list