Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wish: Bind include raygui.h and physac.h #2

Open
milen-prg opened this issue Jul 15, 2023 · 12 comments
Open

Wish: Bind include raygui.h and physac.h #2

milen-prg opened this issue Jul 15, 2023 · 12 comments
Labels
help wanted Extra attention is needed

Comments

@milen-prg
Copy link

Please, if it is possible, add support (by json files) for Raylib GUI and Physics addons.

@overdev
Copy link
Owner

overdev commented Aug 8, 2023

Hi, @milen-prg.

The purpose of this project is to facilitate customization according to the user case. It is possible to add support for RayGui and Phyac and it is quite easy to do so. The only thing I'll not be able is to provide you with the binaries compiled with these extensions. Why not? Because I suck with C development and I can't build the project for except win32 x86 64. So, to keep things simple, I avoid doing customization on the C side of the binding.

If you're looking for shared libs, it may be worth to check out vaiorabbit's repo. The only thing I haven't found yet is the json for physac.h, but in that repo you can find instructions on how to generate it.

On the other hand, in case you know how to build or already have the binaries with RayGuy and Physac extensions included, I can give you directions on how to use the generator to do include them in the binding.

@milen-prg
Copy link
Author

milen-prg commented Aug 9, 2023

Honestly speaking, I have almost no experience in system programming (I use C and Python for simple physics simulations), so as I learn about vaiorabbit's repo, I try to generate the RayGui and Phyac DLLs (seems successfully), but when I try to use JSON generator, it turned out that must to add clang package to my Python, then to install enormous LLVM-16.0.0-win64.exe and at the end, again errors:

from folder:
\raylib-bindings-0.5.5\generator

I try:
 generator  .\batch_generate.cmd Traceback (most recent call last): File "C:\Users\mlap\Documents\my\raylib-bindings-0.5.5\generator\generate_raylib.py", line 37, in <module> ctx.decl_functions["DrawModelEx"].explicit_name = 'internalDrawModelEx' ~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^ KeyError: 'DrawModelEx'
and also python script directly:
`
 generator  .\generate_raygui.py
Error parsing translation unit.

Yet another raylib wrapper for Ruby

* https://github.com/vaiorabbit/raylib-bindings

[NOTICE] Autogenerated. Do not edit.

require 'ffi'

module Raylib
extend FFI::Library
end
`
And no files was generated.

This is too complex for me.

@overdev
Copy link
Owner

overdev commented Aug 9, 2023

I see. I tried to use some of the DLLs from there too, with no success. When they're loaded, an OSError is raised complaining that they're not valid win32 application.

I guess I'll try to build raygui one more time. It is quite some time since my last attempt. Hopefully things are a little bit easier now.

@milen-prg
Copy link
Author

milen-prg commented Aug 9, 2023

I generate DLLs with Visual Studio 2022 64bit compiler, it did not return error and succeed, but, after that the generate_raygui.py script to make JSON for the raygui.h fails.

@overdev
Copy link
Owner

overdev commented Aug 9, 2023

I'm too dumb even with Visual Studio 😢. I managed to generate the raygui.dll but for some strange reason it fails when I try to load it with ctypes: it can't find the raygui C functions:

image

Can you send me a copy of your binaries so I can try them?

@milen-prg
Copy link
Author

DLLs.zip

@overdev
Copy link
Owner

overdev commented Aug 10, 2023

@milen-prg, I have good news.

The funny thing is that we both managed to build the same DLLs with no actual implementation of the functions (having even the same size). When I tried to load your DLL, ctypes gave the same complaint from the print above.

After felling lost, frustrated, despaired and shaking my fist to the pseudo C compiler gods, I decided to try and make a new project based on the raylib examples. That stuff is not intuitive, I got to say.

The end result is that I finally managed to compile raygui and physac. The only proof I have ATM to back this claim is this print:

image

You can see a button on the top left part of the window, which is the result of calling

gui_button(Rectangle(30, 30, 60, 25), "Quit")

To accomplish all this, I had to tweak the bind generator but didn't commit the changes yet. This tweak made possible to have a single binding code that spans across multiple binaries.

If you want to compile on you machine, this raylibguiphys.zip contains the visual studio project. You can clone the raylib repo and unzip it inside projects/VS2022 directory. Then compile it.

Otherwise, this Release.zip contains the DLL.

In any case, you need to install raylibpy with the tweaks: raylib_py-4.5.0.post1-py3-none-any.zip. Change file the extension to .whl in case pip complain about this being a zip. To reinstall you can do:

py -m pip install raylib_py-4.5.0.post1-py3-none-any.whl --force-reinstall

On your python project, two new requirements will need to be fullfilled:
First is to create a .raylib file somewhere in you project, which is justa a JSON file having at least this as content:

{
  "rayguiphys": {
    "win32": {
      "64bit": "change/this/to/indicate/where/the/dll/is"
    }
  }
}

It is important to know that raylibpy will look for this file wherever the current working directory points to when loading. This is the second requirement.

Hopefully, this weekend I'll commit the changes made so far.

Let me know if you find any loading the DLL with raylibpy.

@milen-prg
Copy link
Author

milen-prg commented Aug 11, 2023

I successfully install raylib_py-4.5.0.post1-py3-none-any.whl, then copied the raylibguiphys.dll in project folder. I copied there also the generated file myout, renamed to myraylib.py, with commant:

python raylibpyctbg -typeAnnotate -snakecase -attribSwizzling -bindApi -addVectorMath --libBaseDir ./ --win32LibFilename raylibguiphys.dll --include rmath --include rlgl --out ./myout --markdown ./mydoc

then I try the example:

`

from raylibpy import * ## 1
#from myraylib import * ## 2

def main():

init_window(800, 450, "raylib [core] example - basic window")

set_target_fps(60)

while not window_should_close():

    begin_drawing()
    clear_background(RAYWHITE)
    draw_text("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY)
    end_drawing()

close_window()

if name == 'main':
main()
`

This not work, the error messages are:

1 (with: from raylibpy import *)


Library loading info:
platform: win32
bitness: 64bit
absolute path: c:\python311\lib\site-packages\raylibpy\bin\64bit\raylib.dll
using .raylib file: no
exists: yes
is file: yes

Shared library loaded succesfully <CDLLEx 'c:\python311\lib\site-packages\raylibpy\bin\64bit\raylib.dll', handle 7ffae9850000 at 0x2283bfb36d0>
Library loading info:
platform: win32
bitness: 64bit
.raylib load info: ERROR: Platform (rayguiphys), bitness (win32) or valid filename not specified in .raylib file for 64bit extension
absolute path:
using .raylib file: no
exists: no
is file: no

Failed to load Shared library rayguiphys

Other:

2 (with: from myraylib import *)


Library loading info:
platform: win32
bitness: 64bit
current working dir: C:\Users\mlap\Documents\Milen\MilenWork\raylibpyctbg_prbs1
absolute path: c:\users\mlap\documents\milen\milenwork\raylibpyctbg_prbs1\raylibguiphys.dll
using .raylib file: yes
exists: yes
is file: yes

Shared library loaded succesfully. <CDLLEx 'c:\users\mlap\documents\milen\milenwork\raylibpyctbg_prbs1\raylibguiphys.dll', handle 7ffb133c0000 at 0x2d9350bf890>
Traceback (most recent call last):
File "C:\Users\mlap\Documents\Milen\MilenWork\raylibpyctbg_prbs1\example1.py", line 2, in
from myraylib import *
File "C:\Users\mlap\Documents\Milen\MilenWork\raylibpyctbg_prbs1\myraylib.py", line 6830, in
InitWindow = wrap(rlapi.InitWindow, [Int, Int, CharPtr], None)
File "C:\Python311\Lib\ctypes_init
.py", line 389, in getattr
func = self.getitem(name)
File "C:\Python311\Lib\ctypes_init
.py", line 394, in getitem
func = self._FuncPtr((name_or_ordinal, self))
AttributeError: function 'InitWindow' not found

Seems that the DLL loads, but there are problems with the names.

Also the .raylib must be:
{
"win32": {
"64bit": "raylibguiphys.dll"
}
}

otherwise at:

{
"rayguiphys": {
"win32": {
"64bit": "raylibguiphys.dll"
}
}

the result was:

Library loading info:
platform: win32
bitness: 64bit
.raylib load info: Could not decode .raylib file
absolute path: ..\lib\bin\64bit\raylibguiphys.dll
using .raylib file: no
exists: no
is file: no

Unable to load raylibguiphys.dll.
Failed to load shared library.

I apologize, but I really never dig in system programming, always use Python only for simple simulations play etc.

@overdev
Copy link
Owner

overdev commented Aug 11, 2023

I forgot to tell you there was no need to generate anything else. The raylibpy and the dlls are all you need.

The raylibpy package above is an updated one that have de dll only for C raylib (I mean, without raygui and physac) but include the binding code for raylib, raygui and physac. This means an extra dll is required, which is the one provided above in Release.zip.

Having said that, the following steps are:

  1. Install the updated raylibpy;
  2. Copy the extra dll to some directory in your system (preferrably inside your project in case you plan to publish or send it to someone);
  3. Create the .raylib file in your project to indicate where you copied the dll into.
  4. Ensure that the current working directory is the same where the .raylib is located when from raylibpy import * executes. If you don't want to do this on the command line, you can do the following:

In utils.py:

import os
import os.path as path
from contextlib import contextmanager

__all__ = [
    'context_dir'
]

def context_dir(ctxdir):
    '''Temporarily changes the current working directory'''
    current_dir = os.getcwd()
    is path.isfile(ctxdir):
        ctx_dir = path.basename(ctxdir)
    else:
        ctx_dir = ctxdir
    os.chdir(ctx_dir)
    yield
    os.chdir(current_dir)

Then in your main module:

# between other imports...
from utils import context_dir
with context_dir(__file__):
    from raylibpy import *

This will cause raylib to assume that .raylib file is in the same directory of the current python module.

Regarding the contents of .raylib file, you are using the default dll for raylib along with an extra dll for raygui and physac. The only file location that needs to be indicated in it is the extra dll location. If you wanted to use an alternative dll for raylib, you could indicate its location in it too.
In any case, when an extra or alternative dll needs to be used, it is necessary to indicate 4 things (4 in the updated package you have installed, 3 on old versions): the lib name, the platform, whether it is 32 or 64 bits and the file path.
In your case, the .raylib must be like the example above: the extra dll have 'rayguiphys' as lib name, platform 'win32', '64bit' and is located wherewer you put it.

{
"rayguiphys": {
    "win32": {
        "64bit": "path/to/file.dll"
    }
}
}

It may sound a bit complicated but you'll get used to it.

@milen-prg
Copy link
Author

I have example.py, .raylib, raylib.dll and raylibguiphys.dll in one folder.

example.py:

`from raylibpy import *

def main():

init_window(800, 450, "raylib [core] example - basic window")

set_target_fps(60)

while not window_should_close():

    begin_drawing()
    clear_background(RAYWHITE)
    draw_text("Congrats! You created your first window!", 190, 200, 20, LIGHTGRAY)
    end_drawing()

close_window()

if name == 'main':
main()`

.raylib:

`{
"rayguiphys": {
"win32": {
"64bit": "raylibguiphys.dll"
}
},
"raylib": {
"win32": {
"64bit": "raylib.dll"
}
}
}

`

and the result:

py example1.py

Library loading info:
platform: win32
bitness: 64bit
absolute path: raylib.dll
using .raylib file: no
exists: yes
is file: yes

Shared library loaded succesfully <CDLLEx 'raylib.dll', handle 7ff972890000 at 0x10642568390>
Library loading info:
platform: win32
bitness: 64bit
absolute path: raylibguiphys.dll
using .raylib file: no
exists: yes
is file: yes

Shared library loaded succesfully <CDLLEx 'raylibguiphys.dll', handle 7ff973780000 at 0x106426abe90>
Traceback (most recent call last):
File "C:\Users\mlap\Documents\Milen\MilenWork\raylibpyctbg_prbs1\example1.py", line 1, in
from raylibpy import *
File "C:\Python311\Lib\site-packages\raylibpy_init_.py", line 6069, in
class PhysicsShape(Structure):
File "C:\Python311\Lib\site-packages\raylibpy_init_.py", line 6072, in PhysicsShape
('type', PhysicsShapeType),
^^^^^^^^^^^^^^^^
NameError: name 'PhysicsShapeType' is not defined

Seems, the two DLL are successfully loaded, but there is problem with name definitions.

@overdev
Copy link
Owner

overdev commented Aug 13, 2023

Sadly I come to the conclusion that Physac can't be wrapped in Python. Or, at least, I don't know how to solve it.

I solved the PhysicsShapeType error but ended up with another problem even worse than this.

Physac has circular references in its structure definitions that render impossible do wrap with ctypes. If you take a look in the header file, you'll see that PhysicsBodyData struct have a field named shape that is of type PhysicsShape, which in turn have a field named body of type PhysiscBody that is no other than a pointer to PhysicsBodyData.

Although this works in C, It will always cause a NameError in Python.

@overdev overdev added the help wanted Extra attention is needed label Aug 13, 2023
@charles-esterbrook
Copy link

Python allows circular type refs if one of them is quoted:

thing: 'Thing'  # quotes allow a forward reference

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants