Few cents about my commits

tutorial: RoboVM and Struct pointers mess

|

A struct in the C is a composite data type placed under one name in a block of memory, allowing the different variables to be accessed via a single pointer wiki.
The Bro Java to Native Bridge supports structs data type. And there are several scenarios how they are used:

Functiona parameters: @ByRef and @ByVal

In C world there are two ways to pass struct to function:
By value – struct is passed as parameter (it is copied and the copy is passed):

// c-code
typedef struct {float f;} StructF;
void byValue(StructF s) {
    s.f = 5.4f;
}

void main() {
    StructF ss = {1.0};
    byValue(ss);  // ss is not changed
}

By reference(pointer) – pointer to struct is passed as parameter and no copy being made. All changes to struct made in function affects original struct being passed.

// c-code
void byPointer(StructF *s) {
    s.f = 5.4f;
}

void main() {
    StructF ss = {1.0};
    byValue(&ss);  // ss.f == 5.4 now 
}

In RoboVM Java world there is no such thing as Struct and it is represented by corresponding Class and class instances are passed as references. To tell Bro bridge what code to generate @ByRef and @ByVal annotations are used:

// java-code
native void byValue(@ByVal StructF s); // will make a copy and pass by value
native void byPointer(@ByRef StructF s); // will pass a pointer
native void byPointer2(StructF s); // default: also will pass a pointer

Function return type: @ByRef and @ByVal

Similary native function can return struct (@ByVal) or pointer to it (@ByRef). Specifying valid is requred to get valid result:

// java-code
native @ByVal StructF returnByValue(); 
native @ByRef StructF returnByPointer(); 
native StructF alsoReturnByPointer(); 

Array of Structs

Array of structures is C is passed and returned by pointer to first struct:

// c-code
typedef struct {float f;} StructF;
void parameterStructArray(StructF *s, size_t size) {
    s[size - 1].f = 0;
}

StructF someArray[1000];
StructF* returnStructArray() {
    return someArray;
}

void main() {
    StructF ss[1000] = {0};
    parameterStructArray(ss, 1000); 

    StructF ret = returnStructArray();
    ret[0].f = 0;
}

As in C world these are pointers – in RoboVM Java world these have to be used as @ByRef:

// java-code
native void parameterStructArray(@ByRef StructF s, long size); 
native @ByRef StructF returnStructArray(); 

There is no RoboVM class to reflect array of structures. This functionality is part of base org.robovm.rt.bro.Struct. Creating array of required size:

// java-code
// creating VectorFloat2[100]
int size = 100;
VectorFloat2 structArray = VectorFloat2.allocate(VectorFloat2.class, 100)
// to set data structArray.update() APIs 

iterrating over array of Structs in RoboVM

To iterrate over array of struct that represented by subclass of org.robovm.rt.bro.Struct it is required to know size of array. There are multiple options for this:

// java-code
int size = 100;
VectorFloat2 structArray = VectorFloat2.allocate(VectorFloat2.class, size)
// convert to java array
VectorFloat2 asArray[] = structArray.toArray(size);
// convert to java list 
List<VectorFloat2> asList[] = structArray.toList(size);
// get the iterrator 
Iterator<VectorFloat2> it = structArray.iterator(size);

BEWARE: Struct.Ptr

Bro-gen generates static inner classes for each struct with Ptr suffix, such as:

public static class VectorFloat2Ptr extends Ptr<VectorFloat2, VectorFloat2Ptr> {}

There few moments about it:

  • it shall be used with @ByVal annotation most of the time. As org.robovm.rt.bro.ptr.Ptr is a Struct itself. And if it used as @ByRef it represent pointer to pointer to struct.
  • it is not sutable for iterating over arrays of structs, as Ptr is standalone struct and all iteration API will iterrate on array of pointers to structs.
// java-code
native @ByVal VectorFloat2.VectorFloat2Ptr getPointer();
void foo() {
    VectorFloat2.VectorFloat2Ptr ptr = getPointer();
    // get first element
    VectorFloat2 value = ptr.get();
    // if pointer to array -- get iterator from first element
    VectorFloat2 arr[] = value.toArray(100);
}

Fixing array issue in RoboVm CocoaTouch

Due to the bug in bro-gen there was lot of wrong bindings generated for Pointers to vectorized structs. PR348 fixes these issues.

Comments