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.C;
  35 import java.nicl.metadata.CallingConvention;
  36 import java.nicl.metadata.NativeHeader;
  37 import java.nicl.metadata.NativeType;
  38 import java.nicl.metadata.Offset;
  39 import java.nicl.types.LayoutType;
  40 import java.nicl.types.Pointer;
  41 import java.nicl.types.Struct;
  42 
  43 public class StructUpcall {
  44     private static final boolean DEBUG = false;
  45 
  46     @NativeHeader
  47     public static interface Index {
  48         @NativeType(layout="[iiippp]", ctype="dummy", size=40, isRecordType=true)
  49         @C(file="dummy", line=47, column=11, USR="C:@S@MyStruct")
  50         static interface MyStruct extends Struct<MyStruct> {
  51             @Offset(offset=0l)
  52             @C(file="dummy", line=47, column=11, USR="c:@SA@MyStruct@FI@field1")
  53             @NativeType(layout="i", ctype="enum MyStructField1", size=4l)
  54             int field1$get();
  55             void field1$set(int i);
  56 
  57             @Offset(offset=32l)
  58             @C(file="dummy", line=47, column=11, USR="c:@SA@MyStruct@FI@field2")
  59             @NativeType(layout="i", ctype="int", size=4l)
  60             int field2$get();
  61             void field2$set(int i);
  62 
  63             @Offset(offset=64l)
  64             @C(file="dummy", line=47, column=11, USR="c:@SA@MyStruct@FI@field3")
  65             @NativeType(layout="i", ctype="int", size=4l)
  66             int field3$get();
  67             void field3$set(int i);
  68 
  69             @Offset(offset=128l)
  70             @C(file="dummy", line=47, column=11, USR="c:@SA@MyStruct@FI@field4")
  71             @NativeType(layout="p", ctype="const void *", size=8l)
  72             Pointer<Void> field4$get();
  73             void field4$set(Pointer<?> p);
  74 
  75             @Offset(offset=192l)
  76             @C(file="dummy", line=47, column=11, USR="c:@SA@MyStruct@FI@field5")
  77             @NativeType(layout="p", ctype="const void *", size=8l)
  78             Pointer<Void> field5$get();
  79             void field5$set(Pointer<?> p);
  80 
  81             @Offset(offset=256l)
  82             @C(file="dummy", line=47, column=11, USR="c:@SA@MyStruct@FI@field6")
  83             @NativeType(layout="p", ctype="const void *", size=8l)
  84             Pointer<Void> field6$get();
  85             void field6$set(Pointer<?> p);
  86         }
  87 
  88         @FunctionalInterface
  89         static interface MyStructVisitor {
  90             @C(file="dummy", line=47, column=11, USR="c:@F@slowsort")
  91             @NativeType(layout="([iiippp])V", ctype="void (dummy)", size=4l)
  92             @CallingConvention(value=1)
  93             public void fn(MyStruct s);
  94         }
  95 
  96         @C(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", size=1)
  98         @CallingConvention(value=1)
  99         public abstract void struct_upcall(MyStructVisitor v, MyStruct s);
 100     }
 101 
 102 
 103     public static class MyStructVisitorImpl implements Index.MyStructVisitor {
 104         MyStructVisitorImpl() {
 105         }
 106 
 107         @Override
 108         public void fn(Index.MyStruct s) {
 109             if (DEBUG) {
 110                 System.err.println("visit(" + s + ")");
 111                 System.err.println("\ts.field1  = " + s.field1$get());
 112                 System.err.println("\ts.field2 = " + s.field2$get());
 113                 System.err.println("\ts.field3 = " + s.field3$get());
 114                 System.err.println("\ts.field4 = " + s.field4$get().cast(NativeTypes.INT8).get());
 115                 System.err.println("\ts.field5 = " + s.field5$get().cast(NativeTypes.INT8).get());
 116                 System.err.println("\ts.field6 = " + s.field6$get().cast(NativeTypes.INT8).get());
 117             }
 118 
 119             assertEquals(47, s.field1$get());
 120             assertEquals(11, s.field2$get());
 121             assertEquals(93, s.field3$get());
 122             assertEquals(123, s.field4$get().cast(NativeTypes.UINT8).get());
 123             assertEquals(124, s.field5$get().cast(NativeTypes.UINT8).get());
 124             assertEquals(125, s.field6$get().cast(NativeTypes.UINT8).get());
 125         }
 126     }
 127 
 128     public void test() {
 129         Index i = Libraries.bind(Index.class, Libraries.loadLibrary(MethodHandles.lookup(), "Upcall"));
 130 
 131         try (Scope scope = Scope.newNativeScope()) {
 132             Index.MyStruct s = scope.allocateStruct(Index.MyStruct.class);
 133 
 134             Pointer<Byte> p1 = scope.allocate(NativeTypes.INT8);
 135             Pointer<Byte> p2 = scope.allocate(NativeTypes.INT8);
 136             Pointer<Byte> p3 = scope.allocate(NativeTypes.INT8);
 137 
 138             p1.set((byte)123);
 139             p2.set((byte)124);
 140             p3.set((byte)125);
 141 
 142             s.field1$set(47);
 143             s.field2$set(11);
 144             s.field3$set(93);
 145             s.field4$set(p1.cast(NativeTypes.VOID));
 146             s.field5$set(p2.cast(NativeTypes.VOID));
 147             s.field6$set(p3.cast(NativeTypes.VOID));
 148 
 149             assertEquals(47, s.field1$get());
 150             assertEquals(11, s.field2$get());
 151             assertEquals(93, s.field3$get());
 152             assertEquals(123, s.field4$get().cast(NativeTypes.INT8).get());
 153             assertEquals(124, s.field5$get().cast(NativeTypes.INT8).get());
 154             assertEquals(125, s.field6$get().cast(NativeTypes.INT8).get());
 155 
 156             Index.MyStructVisitor v = new MyStructVisitorImpl();
 157 
 158             i.struct_upcall(v, s);
 159         }
 160 
 161         if (DEBUG) {
 162             System.err.println("back in test()\n");
 163         }
 164     }
 165 
 166     static void assertEquals(long expected, long actual) {
 167         if (expected != actual) {
 168             throw new RuntimeException("expected: " + expected + " does not match actual: " + actual);
 169         }
 170     }
 171 
 172     public static void main(String[] args) {
 173         new StructUpcall().test();
 174     }
 175 }