Skip to content

Update CInterfaceTutorial with additional struct member types #9616

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,38 @@ void c_print(void *thread, char* cstr) {

void fill(my_data* data) {
int i;
printf("**** In C: fill ****\n");
data->f_primitive = 42;
for (i = 0; i < DATA_ARRAY_LENGTH; i++) {
data->f_array[i] = i * 2;
}

data->f_cstr = "Hello World";
data->f_print_function = &c_print;

// additional examples
// enum
data->f_day = MONDAY;

// sub struct member
data->f_sub_struct->f_sub_primitive = 43;

// array of strings
data->f_str_array[0] = "str 0";
data->f_str_array[1] = "str 1";
data->f_str_array[2] = "str 2";
data->f_str_array[3] = "str 3";

// init members from an array of sub structs
for (i = 0; i < DATA_ARRAY_LENGTH; i++) {
data->f_sub_struct_array[i].f_sub_primitive = i;
}

}

void dump(void *thread, my_data* data) {
int i;
printf("**** In C ****\n");
printf("**** In C: dump ****\n");
printf("primitive: %d\n", data->f_primitive);
printf("length: %d\n", DATA_ARRAY_LENGTH);
for (i = 0; i < DATA_ARRAY_LENGTH; i++) {
Expand All @@ -60,6 +80,15 @@ void dump(void *thread, my_data* data) {

/* Call a function pointer. When set to a Java function, this transparently calls a Java function. */
data->f_print_function(thread, data->f_cstr);

printf("f_day: %d\n", data->f_day);
printf("f_sub_struct->f_sub_primitive: %d\n", data->f_sub_struct->f_sub_primitive);
for (i = 0; i < DATA_ARRAY_LENGTH; i++) {
printf("f_str_array[%d]: %s\n", i, data->f_str_array[i]);
}
for (i = 0; i < DATA_ARRAY_LENGTH; i++) {
printf("f_sub_struct_array[%d].f_sub_primitive: %d\n", i, data->f_sub_struct_array[i].f_sub_primitive);
}
}

day_of_the_week_t day_of_the_week_add(day_of_the_week_t day, int offset) {
Expand All @@ -68,7 +97,7 @@ day_of_the_week_t day_of_the_week_add(day_of_the_week_t day, int offset) {

du_t* makeUnion(unsigned char type) {
du_t* result;
printf("**** In C ****\n");
printf("**** In C: makeUnion ****\n");
switch(type) {
case 1:
result = (du_t*) malloc(sizeof(d1_t));
Expand Down
37 changes: 27 additions & 10 deletions substratevm/src/com.oracle.svm.tutorial/native/mydata.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,20 @@

#define DATA_ARRAY_LENGTH 4

typedef enum {
MONDAY = 0,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY,
} day_of_the_week_t;

typedef struct my_data_sub_struct {
int f_sub_primitive;
} my_sub_t;

typedef struct my_data_struct {
int f_primitive;
int f_array[DATA_ARRAY_LENGTH];
Expand All @@ -34,17 +48,20 @@ typedef struct my_data_struct {

void (*f_print_function)(void *thread, char* cstr);

} my_data;
// Added fields to flesh out missing examples
// enum field
day_of_the_week_t f_day;

typedef enum {
MONDAY = 0,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY,
SUNDAY,
} day_of_the_week_t;
// ptr to struct field
my_sub_t* f_sub_struct;

// array of strings
char* f_str_array[DATA_ARRAY_LENGTH];

// array of structs
my_sub_t f_sub_struct_array[DATA_ARRAY_LENGTH];

} my_data;

typedef struct header_struct {
unsigned char type;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
package com.oracle.svm.tutorial;

import java.nio.file.Path;
import java.util.Collections;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.graalvm.nativeimage.CurrentIsolate;
import org.graalvm.nativeimage.IsolateThread;
import org.graalvm.nativeimage.ObjectHandle;
Expand All @@ -52,6 +54,7 @@
import org.graalvm.nativeimage.c.struct.CStruct;
import org.graalvm.nativeimage.c.struct.SizeOf;
import org.graalvm.nativeimage.c.type.CCharPointer;
import org.graalvm.nativeimage.c.type.CCharPointerPointer;
import org.graalvm.nativeimage.c.type.CIntPointer;
import org.graalvm.nativeimage.c.type.CLongPointer;
import org.graalvm.nativeimage.c.type.CTypeConversion;
Expand Down Expand Up @@ -89,7 +92,6 @@ interface MyData extends PointerBase {
/* Read access of a field. A call to the function is replaced with a raw memory load. */
@CField("f_primitive")
int getPrimitive();

/* Write access of a field. A call to the function is replaced with a raw memory store. */
@CField("f_primitive")
void setPrimitive(int value);
Expand All @@ -100,21 +102,36 @@ interface MyData extends PointerBase {

@CField("f_cstr")
CCharPointer getCString();

@CField("f_cstr")
void setCString(CCharPointer value);

@CField("f_java_object_handle")
ObjectHandle getJavaObject();

@CField("f_java_object_handle")
void setJavaObject(ObjectHandle value);

@CField("f_print_function")
PrintFunctionPointer getPrintFunction();

@CField("f_print_function")
void setPrintFunction(PrintFunctionPointer printFunction);

/* Note that for enum setters and getters you must use
primitive type not the java Enum type you defined */
@CField("f_day")
int getDay();
@CField("f_day")
void setDay(int day);

/* Setters and getters for sub struct member */
@CField("f_sub_struct")
MySubStruct getSubStruct();
@CField("f_sub_struct")
void setSubStruct(MySubStruct subStruct);

/* Getter for ptr for string array, setter is not needed
as you can set via the returned pointer */
@CFieldAddress("f_str_array")
CCharPointerPointer addressOfStringArray();
}

@CEnum("day_of_the_week_t")
Expand All @@ -138,6 +155,15 @@ enum DayOfTheWeek {
public static native DayOfTheWeek fromCValue(int value);
}

@CStruct("my_sub_t")
interface MySubStruct extends PointerBase {
@CField("f_sub_primitive")
int getSubPrimitive();

@CField("f_sub_primitive")
void setSubPrimitive(int value);
}

/* Import of a C function pointer type. */
interface PrintFunctionPointer extends CFunctionPointer {

Expand Down Expand Up @@ -172,7 +198,7 @@ protected static void printingInJava(@SuppressWarnings("unused") IsolateThread t
protected static CCharPointerHolder pin;

protected static void dump(MyData data) {
System.out.format("**** In Java ****%n");
System.out.format("**** In Java: dump ****%n");
System.out.format("primitive: %d%n", data.getPrimitive());
System.out.format("length: %d%n", getDataLength());
for (int i = 0; i < getDataLength(); i++) {
Expand All @@ -191,11 +217,20 @@ protected static void dump(MyData data) {
}
/* Call a C function indirectly via function pointer. */
data.getPrintFunction().invoke(currentThread, data.getCString());

System.out.println("f_day: " + DayOfTheWeek.fromCValue(data.getDay()));
System.out.println("f_sub_struct->f_sub_primitive: " + data.getSubStruct().getSubPrimitive());
// print string array
CCharPointerPointer strArray = data.addressOfStringArray();
for (int i = 0; i < getDataLength(); i++) {
System.out.println("f_str_array[" + i + "] = " + CTypeConversion.toJavaString(strArray.read(i)));
}
}

/* Java function that can be called directly from C code. */
@CEntryPoint(name = "java_entry_point")
protected static void javaEntryPoint(@SuppressWarnings("unused") IsolateThread thread, MyData data) {
System.out.println("**** In Java: java_entry_point, demonstrating modifying incoming c struct ****");
/* Allocate a C structure in our stack frame. */
MyData copy = StackValue.get(MyData.class);

Expand All @@ -222,11 +257,26 @@ protected static void javaEntryPoint(@SuppressWarnings("unused") IsolateThread t

/* Create a handle to a Java object. */
data.setJavaObject(ObjectHandles.getGlobal().create(javaString));

/* Modify an enum value */
data.setDay(DayOfTheWeek.TUESDAY.getCValue());

/* Modify a sub struct value */
MySubStruct subStruct = data.getSubStruct();
subStruct.setSubPrimitive(100);
data.setSubStruct(subStruct);

/* Modify string array */
CCharPointerPointer strArray = data.addressOfStringArray();
for (int i = 0; i < getDataLength(); i++) {
strArray.write(i, CTypeConversion.toCString("str " + i*2).get());
}
}

/* Java function that can be called directly from C code. */
@CEntryPoint(name = "java_release_data")
protected static void releaseData(@SuppressWarnings("unused") IsolateThread thread, MyData data) {
System.out.println("**** In Java: java_release_data ****");
dump(data);

/* Retrieve the object we have stored in a handle. */
Expand All @@ -250,6 +300,7 @@ protected static void releaseData(@SuppressWarnings("unused") IsolateThread thre
/* Java function for which C enum values are automatically converted to Java enum constants. */
@CEntryPoint(name = "java_print_day")
protected static void printDay(@SuppressWarnings("unused") IsolateThread thread, DayOfTheWeek day) {
System.out.println("*** In Java: java_print_day ***");
System.out.format("Day: %s (Java ordinal: %d, C value: %d)%n", day.name(), day.ordinal(), day.getCValue());
if (!Platform.includedIn(Platform.WINDOWS.class)) {
/*
Expand Down Expand Up @@ -339,7 +390,7 @@ interface Substruct2 extends PointerBase {

@CEntryPoint(name = "java_entry_point2")
protected static void javaEntryPoint2(@SuppressWarnings("unused") IsolateThread thread, Substruct1 s1, Substruct2 s2) {
System.out.println("*** In Java, demonstrating inheritance with @CStruct class");
System.out.println("*** In Java: java_entry_point2, demonstrating inheritance with @CStruct class");
CCharPointer tp1 = s1.typePtr();
CCharPointer tp2 = s2.header().typePtr();
System.out.println("tp1 = 0x" + Long.toHexString(tp1.rawValue()) + " tp2 = 0x" + Long.toHexString(tp2.rawValue()));
Expand All @@ -352,7 +403,7 @@ protected static void javaEntryPoint2(@SuppressWarnings("unused") IsolateThread

System.out.println("s1.header.type = " + s1.type() + " ((Header) s2).type = " + s2.header().type());

System.out.println("*** In Java, demonstrating @CFieldOffset");
System.out.println("*** In Java: demonstrating @CFieldOffset");
System.out.println("offset_of(s1.header) = " + Substruct1.offsetOfHeader());
System.out.println("offset_of(s2.header) = " + s2.offsetOfHeader());
System.out.println("offset_of(s2.f1) = " + s2.offsetOff1().rawValue());
Expand Down Expand Up @@ -416,7 +467,7 @@ interface DU extends PointerBase {

@CEntryPoint(name = "java_entry_point3")
protected static void javaEntryPoint3(@SuppressWarnings("unused") IsolateThread thread, DU du1, DU du2, D1 d1, D2 d2) {
System.out.println("*** In Java, demonstrating access to union type member with @CStruct class");
System.out.println("*** In Java: java_entry_point3, demonstrating access to union type member with @CStruct class");

if (du1.getD1().notEqual(d1)) {
System.out.println("*** Error with Union test1: du1 should be equal to d1");
Expand Down Expand Up @@ -480,6 +531,7 @@ protected static long getUB1AsUnsignedRawValue(@SuppressWarnings("unused") Isola

@CEntryPoint(name = "java_entry_point4")
protected static void javaEntryPoint4(@SuppressWarnings("unused") IsolateThread thread, SUData sudata) {
System.out.println("*** In Java: java_entry_point4, demonstrating access to unsigned integer types in @CStruct class");
int i = 0;
UnsignedWord u = sudata.getUB1Unsigned();
SignedWord s = sudata.getSB1Signed();
Expand Down