Open GavinRay97 opened 3 years ago
I'm considering looking into libclang + file generation (later a template engine would help for sure): in fact you can find already a starting point in https://github.com/kunitoki/june/blob/main/tools/inspect_juce.py where it parses the juce_core.h and list all classes and methods.
I was thinking about implementing a configurable system like a simple shiboken
(the tool they use in Qt to expose Qt to python https://doc.qt.io/qtforpython/shiboken6/index.html which is based on clang) which is using xml directives to select what and how to generate the bindings (with rewrites and everything).
Nice idea of using cppyy, maybe it's easier to get out the reflection data there (as we can do help(obj)
and get pydocs with methods and everything, but probably we lose constness and stuff that Nim might require, as python is duck typed and mutable by default).
Theoretically, we could use https://github.com/deech/libclang_bindings if we want to make the codegen in nim
I've tweaked a bit the juce inspector using liblang and cindex, it's super hacky and not complete, but i was able to generate some bindings that had to manually tweak but not that much.
once i had a minimal juce_core, i could add the other ones and in the end i was able to get a window on screen !
look at https://github.com/kunitoki/june/blob/main/examples/test_app.nim
it's a good milestone i would say, and apart from the codegen, we need to think on how we could use nim templates and macros to make writing the boilerplate easier (because juce uses a lot of inheritance, and that's bad for the current nim c++ interop capabilites).
because of those nim limitations, i find it hard to make a good codegen that needs no modification. for example the juce::DocumentWindow
needs to be derived and closeButtonPressed
should be implemented or nothing will happen when closing the window.
so i had to make juce::DocumentWindow
into nim DocumentWindowImpl
and create a june::DocumentWindow
which became the nim DocumentWindow
, so a cdecl
function pointer could be set in order to have nim code executed in the closeButtonPressed.
all this will be difficult to do with a codegen (or it can be done, but really tedious and error prone).
Compiling and running https://github.com/kunitoki/june/blob/main/examples/test_app.nim will produce:
june (main) $ nimble app_debug
Executing task app_debug in /Users/kunitoki/Documents/june/june.nimble
Hint: used config file '/Users/kunitoki/.choosenim/toolchains/nim-1.6.4/config/nim.cfg' [Conf]
Hint: used config file '/Users/kunitoki/.choosenim/toolchains/nim-1.6.4/config/config.nims' [Conf]
Hint: used config file '/Users/kunitoki/Documents/june/nim.cfg' [Conf]
Hint: used config file '/Users/kunitoki/Documents/june/examples/nim.cfg' [Conf]
.....................................................................................
Hint: [Link]
Hint: dsymutil /Users/kunitoki/Documents/june/examples/test_app [Exec]
Hint: gc: refc; opt: none (DEBUG BUILD, `-d:release` generates faster code)
45364 lines; 3.281s; 75.277MiB peakmem; proj: /Users/kunitoki/Documents/june/examples/test_app.nim; out: /Users/kunitoki/Documents/june/examples/test_app [SuccessX]
JUCE v6.0.8
START_JUCE_APPLICATION enter...
Creating application...
Initialising application...
Starting JUNE App
Starting JUNE App completed
Starting message loop...
Then closing the window...
Finishing message loop...
Finalizing application...
Shutdown JUNE App
Shutdown JUNE App completed
START_JUCE_APPLICATION exit...
Hello, thank you for the collaboration invite =D
I have been investigating + experimenting with converting C++ headers to Dlang
extern (C++)
bindings and also more recently to Nim.Maybe I can share some thoughts/findings with you 🙂
libclang vs LibTooling
Probably not so important for just one library, but I have been doing reading on which approach is best for translating headers to other languages + bindgen/codegen.
There are some screenshots of experiences from the authors of c2rust and dpp:
🌟 Click for relevant parts of conversation 👇
![image](https://user-images.githubusercontent.com/26604994/118817744-8ebd6180-b881-11eb-84c9-25fe65436fbb.png) ![](https://media.discordapp.net/attachments/833812449135951873/833813106035392582/unknown.png) ![](https://media.discordapp.net/attachments/833812449135951873/833813453864042596/unknown.png)It's possible to use
cppyy
for LibTooling access, if you build LLVM on Linux/MinGW withBUILD_SHARED_LIBS
set toON
(I think it's also possible withLLVM_BUILD_DYLIB
)Doing this gives you:
API/codegen approach
I found two interesting approaches others have taken for the actual codegen that I have been experimenting with. Maybe you have some ideas?
The first
Create decorators in Python which hold rules, the argument is a
clang::QualType
orclang::Type
. Nodes are evaluated against rules, the one matching is chosen for codegen.Each class is a "frontend" driver/generator for a language to create from C++ headers. It's very clever! Currently he has:
Here is the repo where I found this. In his approach, he has used
PyBind
for binding the Clang/LibTooling C++ API to Python, which could also be used instead ofcppyy
I suppose (not sure why you'd do that)(PyBind) https://github.com/Time0o/CPPBind/blob/7d7b578112416ea6fa13431edf77b57460799f6c/source/Backend.cpp#L151-L210
The second
Use template languages like Jinja/Moustache to create declarative template files for codegen. This allows easy visualization of what the output will be, and for people to tweak it or pass a custom template file easily.
I saw this approach here:
I imagine that if clang nodes were passed into here, and a template language was used which allowed to evaluate expressions like
t.is_pointer()
then it could actually be pretty okay.The approach with this library for evaluating expressions is by using a custom "hooks" file for defining pre-processing logic.
It's very basic though and does not use clang, but a custom Python preprocessor.