1 /*
   2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @modules java.base/jdk.internal.misc
  27  * @run main/othervm StructUpcall
  28  */
  29 
  30 import java.lang.invoke.MethodHandles;
  31 import java.nicl.Libraries;
  32 import java.nicl.NativeTypes;
  33 import java.nicl.Scope;
  34 import java.nicl.metadata.NativeCallback;
  35 import java.nicl.metadata.NativeHeader;
  36 import java.nicl.metadata.NativeLocation;
  37 import java.nicl.metadata.NativeStruct;
  38 import java.nicl.metadata.NativeType;
  39 import java.nicl.metadata.Offset;
  40 import java.nicl.types.LayoutType;
  41 import java.nicl.types.Pointer;
  42 import java.nicl.types.Struct;
  43 
  44 public class StructUpcall {
  45     private static final boolean DEBUG = false;
  46 
  47     @NativeHeader
  48     public static interface Index {
  49         @NativeLocation(file="dummy", line=47, column=11, USR="C:@S@MyStruct")
  50         @NativeStruct("[iiippp]")
  51         static interface MyStruct extends Struct<MyStruct> {
  52             @Offset(offset=0l)
  53             @NativeLocation(file="dummy", line=47, column=11, USR="c:@SA@MyStruct@FI@field1")
  54             @NativeType(layout="i", ctype="enum MyStructField1")
  55             int field1$get();
  56             void field1$set(int i);
  57 
  58             @Offset(offset=32l)
  59             @NativeLocation(file="dummy", line=47, column=11, USR="c:@SA@MyStruct@FI@field2")
  60             @NativeType(layout="i", ctype="int")
  61             int field2$get();
  62             void field2$set(int i);
  63 
  64             @Offset(offset=64l)
  65             @NativeLocation(file="dummy", line=47, column=11, USR="c:@SA@MyStruct@FI@field3")
  66             @NativeType(layout="i", ctype="int")
  67             int field3$get();
  68             void field3$set(int i);
  69 
  70             @Offset(offset=128l)
  71             @NativeLocation(file="dummy", line=47, column=11, USR="c:@SA@MyStruct@FI@field4")
  72             @NativeType(layout="p", ctype="const void *")
  73             Pointer<Void> field4$get();
  74             void field4$set(Pointer<?> p);
  75 
  76             @Offset(offset=192l)
  77             @NativeLocation(file="dummy", line=47, column=11, USR="c:@SA@MyStruct@FI@field5")
  78             @NativeType(layout="p", ctype="const void *")
  79             Pointer<Void> field5$get();
  80             void field5$set(Pointer<?> p);
  81 
  82             @Offset(offset=256l)
  83             @NativeLocation(file="dummy", line=47, column=11, USR="c:@SA@MyStruct@FI@field6")
  84             @NativeType(layout="p", ctype="const void *")
  85             Pointer<Void> field6$get();
  86             void field6$set(Pointer<?> p);
  87         }
  88 
  89         @NativeCallback("([iiippp])V")
  90         @FunctionalInterface
  91         static interface MyStructVisitor {
  92             @NativeLocation(file="dummy", line=47, column=11, USR="c:@F@slowsort")
  93             public void fn(MyStruct s);
  94         }
  95 
  96         @NativeLocation(file="dummy", line=47, column=11, USR="c:@F@struct_upcall")
  97         @NativeType(layout="(p:([iiip:Vp:Vp:V])V[iiip:Vp:Vp:V])V", ctype="void (struct_upcall_cb, struct MyStruct)", name="struct_upcall")
  98         public abstract void struct_upcall(MyStructVisitor v, MyStruct s);
  99     }
 100 
 101 
 102     public static class MyStructVisitorImpl implements Index.MyStructVisitor {
 103         MyStructVisitorImpl() {
 104         }
 105 
 106         @Override
 107         public void fn(Index.MyStruct s) {
 108             if (DEBUG) {
 109                 System.err.println("visit(" + s + ")");
 110                 System.err.println("\ts.field1  = " + s.field1$get());
 111                 System.err.println("\ts.field2 = " + s.field2$get());
 112                 System.err.println("\ts.field3 = " + s.field3$get());
 113                 System.err.println("\ts.field4 = " + s.field4$get().cast(NativeTypes.INT8).get());
 114                 System.err.println("\ts.field5 = " + s.field5$get().cast(NativeTypes.INT8).get());
 115                 System.err.println("\ts.field6 = " + s.field6$get().cast(NativeTypes.INT8).get());
 116             }
 117 
 118             assertEquals(47, s.field1$get());
 119             assertEquals(11, s.field2$get());
 120             assertEquals(93, s.field3$get());
 121             assertEquals(123, s.field4$get().cast(NativeTypes.UINT8).get());
 122             assertEquals(124, s.field5$get().cast(NativeTypes.UINT8).get());
 123             assertEquals(125, s.field6$get().cast(NativeTypes.UINT8).get());
 124         }
 125     }
 126 
 127     public void test() {
 128         Index i = Libraries.bind(Index.class, Libraries.loadLibrary(MethodHandles.lookup(), "Upcall"));
 129 
 130         try (Scope scope = Scope.newNativeScope()) {
 131             Index.MyStruct s = scope.allocateStruct(Index.MyStruct.class);
 132 
 133             Pointer<Byte> p1 = scope.allocate(NativeTypes.INT8);
 134             Pointer<Byte> p2 = scope.allocate(NativeTypes.INT8);
 135             Pointer<Byte> p3 = scope.allocate(NativeTypes.INT8);
 136 
 137             p1.set((byte)123);
 138             p2.set((byte)124);
 139             p3.set((byte)125);
 140 
 141             s.field1$set(47);
 142             s.field2$set(11);
 143             s.field3$set(93);
 144             s.field4$set(p1.cast(NativeTypes.VOID));
 145             s.field5$set(p2.cast(NativeTypes.VOID));
 146             s.field6$set(p3.cast(NativeTypes.VOID));
 147 
 148             assertEquals(47, s.field1$get());
 149             assertEquals(11, s.field2$get());
 150             assertEquals(93, s.field3$get());
 151             assertEquals(123, s.field4$get().cast(NativeTypes.INT8).get());
 152             assertEquals(124, s.field5$get().cast(NativeTypes.INT8).get());
 153             assertEquals(125, s.field6$get().cast(NativeTypes.INT8).get());
 154 
 155             Index.MyStructVisitor v = new MyStructVisitorImpl();
 156 
 157             i.struct_upcall(v, s);
 158         }
 159 
 160         if (DEBUG) {
 161             System.err.println("back in test()\n");
 162         }
 163     }
 164 
 165     static void assertEquals(long expected, long actual) {
 166         if (expected != actual) {
 167             throw new RuntimeException("expected: " + expected + " does not match actual: " + actual);
 168         }
 169     }
 170 
 171     public static void main(String[] args) {
 172         new StructUpcall().test();
 173     }
 174 }