Binding Help

Started by gudenau, August 20, 2017, 02:27:18

Previous topic - Next topic

gudenau

I am working on adding a binding to LWJGL3 that could be useful for development of games.

I have been converting the header file to the Kotlan stuff based on the GLFW files, so far I don't have errors and I think I understand the structure of the enums and defines, my current problem is that when I test built it to check the Java output my binding was not in the release.

What did I do wrong? I added my files in templates/src/main/kotlin/org/lwjgl/library/libraryTypes.kt and templates/src/main/kotlin/org/lwjgl/library/templates/library.kt.

(also to the mods, sorry for making a couple posts so close. Figured these where different enough to warrant that)

gudenau

I've managed to get it to build to a degree by adding the library to /config/build-bindings.xml, looks like I probably need to add it to the other platform ones as well.

spasi

Hey gudenau,

See this commit of the recently added rpmalloc bindings as an example. These are the non-obvious places where changes need to happen:

- /build.xml
- /build.gradle (missing in the above commit, added with this one)
- /config/build-bindings.xml
- /config/linux/build.xml
- /config/macos/build.xml
- /config/windows/build.xml
- /modules/generator/src/main/kotlin/org/lwjgl/generator/Generator.kt

gudenau

Quote from: spasi on August 22, 2017, 09:57:30
Hey gudenau,

See this commit of the recently added rpmalloc bindings as an example. These are the non-obvious places where changes need to happen:

- /build.xml
- /build.gradle (missing in the above commit, added with this one)
- /config/build-bindings.xml
- /config/linux/build.xml
- /config/macos/build.xml
- /config/windows/build.xml
- /modules/generator/src/main/kotlin/org/lwjgl/generator/Generator.kt

I found those using grep, any way this could be streamlined any more?

spasi

Quote from: gudenau on August 22, 2017, 19:48:10any way this could be streamlined any more?

It's probably going to be simpler/cleaner when we port the Ant build to Gradle/Kotlin.

gudenau

Now I have another issue, there is a recursive definition in a header.

Basically this:
C:
struct structure;

typedef void (*callbackMethod)(struct structure *data);

struct structure{
    callbackMethod callback;
}

Kotlin:
var structure = struct(
    LIBRARY_PACKAGE,
    "structure"
){
    callback.member("callback", "")
}

var callback = "callback".callback(
    LIBRARY_PACKAGE, void,
    "callback", "",
    structure.p.IN("data", "")
)


How do I resolve this? It says to define types explicitly and I am not sure what that means, I know nothing about Kotlin.

spasi

This happens often with structs that are defined in a linked-list manner. To break the recursion, you define a struct type without a body. Everything should be in the same order as the C definitions:

var structure_p = struct(LIBRARY_PACKAGE, "structure").p // declare the struct type (as a pointer to a yet undefined struct)

var callback = "callback".callback(
    LIBRARY_PACKAGE, void,
    "callback", "",

    structure_p.IN("data", "")
)

var structure = struct(LIBRARY_PACKAGE, "structure") { // define the struct type
    callback.member("callback", "")
}

gudenau

Quote from: spasi on October 02, 2017, 06:42:10
This happens often with structs that are defined in a linked-list manner. To break the recursion, you define a struct type without a body. Everything should be in the same order as the C definitions:

var structure_p = struct(LIBRARY_PACKAGE, "structure").p // declare the struct type (as a pointer to a yet undefined struct)

var callback = "callback".callback(
    LIBRARY_PACKAGE, void,
    "callback", "",

    structure_p.IN("data", "")
)

var structure = struct(LIBRARY_PACKAGE, "structure") { // define the struct type
    callback.member("callback", "")
}


Thanks!

Sorry for being such an idiot with this stuff. :-/

spasi

Quote from: gudenau on October 02, 2017, 15:47:28Sorry for being such an idiot with this stuff. :-/

It's OK, the template DSL is anything but friendly. It's the reason very few people have been able to make binding contributions.

gudenau

Next issue that I have not found a fix for:

There is a function that has a return type of struct strucutre**`, a null terminated array of structs. How can I make this work when the library allocates the memory for this? NullTerminated and PointerArray do not seem to work for this.

spasi

Quote from: gudenau on October 02, 2017, 18:04:10There is a function that has a return type of struct strucutre**`, a null terminated array of structs

That sounds odd. Isn't there an output parameter that returns the array size? Could you post more details about the function? (i.e. signature and documentation)

gudenau

Quote from: spasi on October 02, 2017, 19:20:34
Quote from: gudenau on October 02, 2017, 18:04:10There is a function that has a return type of struct strucutre**`, a null terminated array of structs

That sounds odd. Isn't there an output parameter that returns the array size? Could you post more details about the function? (i.e. signature and documentation)

I agree, it is quite odd as it goes. There is a free method that you need to call though, at least you can clean it up.

Definition in the headers:
const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds(libusb_context *ctx);


Then the documentation for the function:
Quote
const struct libusb_pollfd** libusb_get_pollfds   (   libusb_context *    ctx   )   
Retrieve a list of file descriptors that should be polled by your main loop as libusb event sources.

The returned list is NULL-terminated and should be freed with libusb_free_pollfds() when done. The actual list contents must not be touched.

As file descriptors are a Unix-specific concept, this function is not available on Windows and will always return NULL.

Parameters
ctx   the context to operate on, or NULL for the default context
Returns
a NULL-terminated list of libusb_pollfd structures
NULL on error
NULL on platforms where the functionality is not available

spasi

You could try something like this:

// replace struct libusb_pollfd** with an opaque pointer
const..opaque_p(
    "get_pollfds",
    "",

    libusb_context.p.IN("ctx", "")
)

// example usage:
LibUSBPollFD fd;
for (long pp = libusb_get_pollfds(ctx); (fd = LibUSBPollFD.create(memGetAddress(pp))) != null; pp += POINTER_SIZE) {
    // ...use file descriptor...
}


If this style occurs again, I'll try to add NullTerminated support to return values. The above would become:

PointerBuffer pp = libusb_get_pollfds(ctx);
for (int i = 0; i < pp.remaining(); i++) {
    LibUSBPollFD fd = LibUSBPollFD.create(pp.get(i));
    // ...use file descriptor...
}

gudenau

Nice, I made it generate source files that break the java compiler with comments ending early. :-P

gudenau

I presume I should use an opaque pointer for the structs that have no body in the headers?