[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