-
-
Save Spasi/41832fe66f3a8c770948 to your computer and use it in GitHub Desktop.
Zero-overhead, type-safe native interop with Kotlin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// WARNING: This is not valid Kotlin code. The typealias keyword | |
// has not been implemented yet and may not work as shown below. | |
// This is like a C typedef. You can pass a GLint/GLenum where an | |
// Int is expected, but you cannot do the opposite, would be a | |
// compile-time error. | |
typealias GLint = Int | |
typealias GLenum = Int | |
// Native pointer values are usually mapped to Java longs. We can | |
// get fancy here with type parameters (e.g. Pointer<Foo>) or be | |
// more specific (e.g. UINT32Pointer), but lets just treat this as | |
// an opaque pointer to an arbitrary native data structure. | |
typealias Pointer = Long | |
// Lets use GLsync from the ARB_sync OpenGL extension. This is an | |
// alias to an alias, so GLsync is still a primitive long. | |
typealias GLsync = Pointer | |
// We cannot assign Long to Pointer, so a cast is necessary. | |
public val NULL: Pointer = 0L as Pointer | |
// The following definitions would be auto-generated by LWJGL. | |
public val GL_SYNC_GPU_COMMANDS_COMPLETE: GLenum = 0x9117 as GLenum | |
public val GL_OBJECT_TYPE: GLenum = 0x9112 as GLenum | |
public val GL_SYNC_CONDITION: GLenum = 0x9113 as GLenum | |
public val GL_SYNC_STATUS: GLenum = 0x9114 as GLenum | |
public val GL_SYNC_FLAGS: GLenum = 0x9115 as GLenum | |
public val GL_UNSIGNALED: GLint = 0x9118 as GLint | |
public val GL_SIGNALED : GLint = 0x9119 as GLint | |
// virtual constructor | |
public fun GLsync(condition: GLenum, flags: Int): GLsync = | |
GL32.glFenceSync(condition, flags) as GLsync // glFenceSync returns a long, cast to GLsync | |
// extension function on the typealias | |
public fun GLsync.get(pname: GLenum): GLint = | |
GL32.glGetSynci(this, pname, NULL) as GLint | |
fun test() { | |
// We cannot pass simple ints to GLenum parameters. | |
// Also, auto-complete suggests GLenums only. | |
val sync = GLsync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0) | |
glFinish() | |
// sync is just a long in bytecode, but in Kotlin | |
// we can use all kinds of goodies. | |
assertTrue(sync[GL_SYNC_STATUS], GL_SIGNALED) | |
} | |
// Structs are interesting too: | |
typealias BytePointer = Pointer // char* | |
// sun.misc.Unsafe stuff | |
fun BytePointer.get(offset: Int): Byte = memGetByte(this + offset) | |
fun BytePointer.set(offset: Int, value: Byte): Unit = memPutByte(this + offset, value) | |
// Generated | |
typealias GLFWimage = Pointer | |
var GLFWimage.width: Int | |
get() = memGetInt(this + 0) | |
set(width: Int) = memPutInt(this + 0, width) | |
var GLFWimage.height: Int | |
get() = memGetInt(this + 4) | |
set(height: Int) = memPutInt(this + 4, height) | |
val GLFWimage.pixels: BytePointer | |
get() = memGetAddress(8) as BytePointer | |
fun testStructs() { | |
val img: GLFWimage = ... | |
img.width = 32 | |
img.height = 32 | |
for ( y in 0..31 ) { | |
for ( x in 0..31 ) { | |
img.pixels[y * 32 + x] = 127 | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment