electronstudio / jaylib

Java JNI bindings for Raylib
Other
106 stars 18 forks source link

Use arrays instead of structs #50

Open glowiak opened 1 month ago

glowiak commented 1 month ago

In order to use the Pro and Ex functions you often need to pass the values using RL structs like Vector2 or Rectangle.

In C you can just use it as an array with a cast to the struct type: (Vector2){0.0f, 0.0f}.

In Java you have to allocate it using the "new" keyword, then manually set its values and possibly later .close() it after using. It is very unhandy.

Considering that both Vector2 and Rectangle are just arrays of floats - of two and four floats respectively, could it be possible to be able to pass float[] in place of Vector2 or Rectangle?

It would be much more pleasant to use and definitely much less frustrating to write.

electronstudio commented 1 month ago

C is sometimes able to ignore the difference between structs and arrays because it is weakly typed, so you can pretend one type is a different type, and all types are value types, so arrays are linear in memory. Java is strongly typed, and currently only has value types for primitives.

However in your example I don't think (Vector2){0.0f, 0.0f} is creating an array, it's just a nicer syntax for initializing a struct. If you want the safety of Java but you don't like the verbose syntax it entails (e.g. the new keyword) you might prefer to use Kotlin.

The easiest way to do what you want in Java is to write a function that takes an array of floats and returns a Vector2 and call that function in your code as required.

If you mean actually change the API everywhere to take arrays instead of Vector2s I think this might be possible by doing a search and replace in the raylib.h file and changing the types before the binding is generated. I doubt it though, and that loss of type safety wouldn't be what most Java programmers would want.

It sounds like what you really want is a wrapper in Java around the functions which take Vector2. so there would be an alternative version of each which takes 2 floats instead of a Vector2. Unlike arrays, that would be type safe. I don't like putting stuff in Jaylib that isn't autogenerated but we already have some wrappers in com.raylib.Jaylib class so could maybe put them there. Or just distribute the wrapper yourself separately.

glowiak commented 1 month ago

The easiest way to do what you want in Java is to write a function that takes an array of floats and returns a Vector2 and call that function in your code as required.

That would solve the problem if not performance.

In C small structs are usually converted under the hood to integer values and it consumes no performance. While in Java, using the 'new' struct causes memory allocation, which is way slower than simply passing an integer.

electronstudio commented 1 month ago

Actually if this were a pure Java library then using ‘new’ probably wouldn’t cause heap allocations. Java is smart enough to figure out the temporary objects aren’t necessary and rewrite the code so they never even created.

But since it’s a JNI (JavaCPP) library it can’t do that. Structs have to be allocated on the native heap before they can be passed to C. I can’t see how to avoid that other than rewriting Raylib to change the function parameters.

If you want more control over the allocation and improved performance then that’s what Jaylib-FFM is for.