Nuklear.jl - A Julia wrapper for Nuklear?

Hello,

Nuklear is graphical user interface toolkit written in ANSI C.
It’s a single header library written in C89 (ANSI C), with small codebase (~18kLOC)
It’s focussed on portability, efficiency and simplicity and have no dependencies.

Documentation is available at https://rawgit.com/vurtun/nuklear/master/doc/nuklear.html
and code at https://github.com/vurtun/nuklear

I wonder if some people have ever considered writing a Julia wrapper for Nuklear

Kind regards

This matter has been discussed before. See this topic

1 Like

It’s not hard to generate Julia bindings using Clang.jl, but those backends need to be reimplemented in Julia. Since the codebase is small, should we reimplement everything in Julia? or is it possible to do a source-to-source translation using Clang.jl?

1 Like

GLFW.jl, SimpleDirectMediaLayer.jl exists and seems to be maintained.
SFML.jl, DirectX.jl and Xlib.jl are currently broken for Julia 0.7/1.0
Not sure about current status of a Julia GDI and a Julia liballeg (Allegro) wrapper.

1 Like

FYI, imgui also has c-bindings:

I’ve registered a package for nuklear:

https://github.com/JuliaLang/METADATA.jl/pull/20455

4 Likes

Thanks @Gnimuc
Great news !
I will give it a try.
Maybe you should make a post at https://discourse.julialang.org/c/community/packages

Currently, it still has some limitations(e.g. cannot call vararg APIs) and I feel like it’s not very convenient to work with nuklear in Julia, for example, ctx->style.button.normal = nk_style_item_color(nk_rgb(40,40,40)); is easy in C, but when we do this in Julia either by pure pointer arithmetic or using Blobs.jl, the code looks ugly and redundant. Maybe we need to extend its APIs with more helper C functions? I’ll try to keep this package actively maintained, so feel free to file issues if you’ve any question.

Very nice @Gnimuc. Would it be possible to have an example that displays an image, and/or a rgb uint8 array?

yep, but I need to implement this backend function firstly:

It’s 11 pm in my local time, I’ll do it tomorrow. :slight_smile:

I noticed in README

  • SFML(pending upstream)
  • SDL(pending upstream)

Working on SFML.jl is required
I did some months ago
https://github.com/zyedidia/SFML.jl/pull/51/files
but more work seems to be required to pass continuous integration.
Any help is welcome !

search function is not continued in Julia v1.0, you could use occursin I guess.

It looks like SFML is not actively maintained(last commit is one year ago). It would be great if we could upgrade the build system to BB2 with which installation related issues would be solved spontaneously. To this end, we need to build those missing BB projects from this list: Frequently Asked Questions (SFML / Learn)

I don’t know whether those wrappers were written by hand or generated using old Clang.jl, but maybe we can regenerate those bindings of the latest CSFML using Clang.jl-v0.8.

Please try this branch:

Thanks. In a train now. Will try it latter tonight.

OK, gave it a try but had some issues. While this works, it creates a very dark image with tinny letters (like having troubles figuring high-res displays?)

include("C:\\Users\\j\\.julia\\packages\\Nuklear\\K7FqF\\demo\\demo.jl")

but the image demo errors with

julia> include("C:\\Users\\j\\.julia\\packages\\Nuklear\\K7FqF\\demo\\image.jl")
ERROR: LoadError: ArgumentError: Package Images not found in current path:
- Run `import Pkg; Pkg.add("Images")` to install the Images package.

Could you upload a screenshot? The default font is ProggyClean.ttf which is indeed very tinny. Nuklear’s font baking API is a little bit complex to work with, I need to add some helper functions in the C side.

I use Images.jl to load and manipulate png format images, you need to install Images.jl to run that demo.

Yes, it works after installing Images.
The font issue. What I see is like a font of size ~5 pts but when I do a screen capture, which is at lower resolution, the image looks as if it has larger fonts. In fact I get one that is similar to yours, so no point uploading it.

I also get this error after deleting the image.

julia> include("C:\\Users\\j\\.julia\\packages\\Nuklear\\jYRiH\\demo\\image.jl")
ERROR: LoadError: ContextNotAvailable("glDeleteProgram, not available for your driver, or no valid OpenGL context available")
Stacktrace:
 [1] getprocaddress_e at C:\Users\j\.julia\packages\ModernGL\oi403\src\ModernGL.jl:41 [inlined]
 [2] glDeleteProgram(::UInt32) at C:\Users\j\.julia\packages\ModernGL\oi403\src\functionloading.jl:37
 [3] nk_glfw3_device_destroy() at C:\Users\j\.julia\packages\Nuklear\jYRiH\src\backend\GLFW\impl.jl:307
 [4] nk_glfw3_shutdown() at C:\Users\j\.julia\packages\Nuklear\jYRiH\src\backend\GLFW\impl.jl:324
 [5] top-level scope at none:0
 [6] include at .\boot.jl:317 [inlined]
 [7] include_relative(::Module, ::String) at .\loading.jl:1044
 [8] include(::Module, ::String) at .\sysimg.jl:29
 [9] include(::String) at .\client.jl:392
 [10] top-level scope at none:0
in expression starting at C:\Users\j\.julia\packages\Nuklear\jYRiH\demo\image.jl:101

The context is destroyed too early when calling GLFW.DestroyWindow.

GLFW.DestroyWindow(win)
nk_glfw3_shutdown()

should be

nk_glfw3_shutdown()
GLFW.DestroyWindow(win)

Scelles, I was also interested in working in SFML.jl. From your changes (thanks about that) I made another one, GitHub - dmolina/SFML.jl: A binding of the game and multimedia library SFML for Julia that solved the continous integration your version had. However, I did not made a PR yet because it is still not working, see Problem porting SFML.jl to Julia 1.1 - #2 by Gnimuc. Any idea? Any help is welcome!

1 Like

Poptart.jl is based on Nuklear.jl.
it’s a very early prototype.

using Poptart.Desktop # Application Windows put!
using Poptart.Controls # Button Label Slider didClick

window1 = Windows.Window(title="A", frame=(x=10,y=20,width=200,height=200))
window2 = Windows.Window(title="B", frame=(x=220,y=20,width=200,height=200))
windows = [window1, window2]
app = Application(windows=windows, title="App", frame=(width=430, height=300))

button = Button(title="Hello", frame=(width=80, height=30))
put!(window1, button)

label = Label(text="Range:")
slider1 = Slider(range=1:10, value=Ref{Cint}(5))
slider2 = Slider(range=1.0:10.0, value=Ref{Cfloat}(2.0))
put!(window2, label, slider1, slider2)

didClick(button) do event
    @info :didClick event
end

didClick(slider1) do event
    @info :didClick (event, slider1.value)
end

3 Likes