Hello Guest

Binding Help

  • 45 Replies
  • 23997 Views
Binding Help
« on: August 20, 2017, 02:27:18 »
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)

Re: Binding Help
« Reply #1 on: August 22, 2017, 01:16:55 »
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.

*

Offline spasi

  • *****
  • 2261
    • WebHotelier
Re: Binding Help
« Reply #2 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

Re: Binding Help
« Reply #3 on: August 22, 2017, 19:48:10 »
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?

*

Offline spasi

  • *****
  • 2261
    • WebHotelier
Re: Binding Help
« Reply #4 on: August 22, 2017, 20:38:27 »
any way this could be streamlined any more?

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

Re: Binding Help
« Reply #5 on: October 01, 2017, 23:38:42 »
Now I have another issue, there is a recursive definition in a header.

Basically this:
C:
Code: [Select]
struct structure;

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

struct structure{
    callbackMethod callback;
}
Kotlin:
Code: [Select]
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.

*

Offline spasi

  • *****
  • 2261
    • WebHotelier
Re: Binding Help
« Reply #6 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:

Code: [Select]
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", "")
}

Re: Binding Help
« Reply #7 on: October 02, 2017, 15:47:28 »
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:

Code: [Select]
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. :-/

*

Offline spasi

  • *****
  • 2261
    • WebHotelier
Re: Binding Help
« Reply #8 on: October 02, 2017, 16:05:34 »
Sorry 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.

Re: Binding Help
« Reply #9 on: October 02, 2017, 18:04:10 »
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.

*

Offline spasi

  • *****
  • 2261
    • WebHotelier
Re: Binding Help
« Reply #10 on: October 02, 2017, 19:20:34 »
There 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)

Re: Binding Help
« Reply #11 on: October 02, 2017, 19:35:17 »
There 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:
Code: [Select]
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

*

Offline spasi

  • *****
  • 2261
    • WebHotelier
Re: Binding Help
« Reply #12 on: October 02, 2017, 21:45:45 »
You could try something like this:

Code: [Select]
// 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:

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

Re: Binding Help
« Reply #13 on: October 03, 2017, 03:04:44 »
Nice, I made it generate source files that break the java compiler with comments ending early. :-P

Re: Binding Help
« Reply #14 on: October 03, 2017, 03:24:40 »
I presume I should use an opaque pointer for the structs that have no body in the headers?