split project into static and dynamic modules

This commit is contained in:
Richard Smith 2019-05-24 04:31:48 +01:00
parent 55dca44b4a
commit b6b9054d0d
28 changed files with 188 additions and 161 deletions

View file

@ -1,6 +1,9 @@
include raylib/*.so
include raylib/*.pyd
exclude raylib/*.a
exclude raylib/*.h
exclude raylib/*.c
exclude raylib/*.o
include raylib/static/*.so
include raylib/static/*.pyd
exclude raylib/static/*.a
exclude raylib/static/*.h
exclude raylib/static/*.c
exclude raylib/static/*.o
include raylib/dynamic/*.dylib
include raylib/dynamic/*.dll
include raylib/dynamic/*.so

View file

@ -35,6 +35,7 @@ you will have to build. The specific version we built against is https://github
* MacOS 10.12.6 - Python 3.7
* Ubuntu 18.04 LTS - Python 3.6
* Windows 10 (64 bit) - Python 3.7
# HELP WANTED
@ -43,10 +44,10 @@ you will have to build. The specific version we built against is https://github
### Dynamic bindings
I have attempted to do CFFI ABI dynamic bindings too in order to avoid the need to compile a C extension module,
but they don't work properly. They fail in the same place the ctypes binding fails, accessing
materials of a model, because Python can't dynamically tell the difference between a pointer and an array. There's probably
some way to specify this (e.g. in raylib_modified.h) but it's difficult to be sure we fixed them all because the errors
are often completely silent.
See test_dynamic.py for the non-working example.
In addition to the API static bindings I have attempted to do CFFI ABI dynamic bindings in order to avoid the need to compile a C extension module.
There have been some weird failures with dynamic bindings and ctypes bindings before and often the failures are silent
so you dont even know. Also the static bindings should be faster. Therefore I recommend the static ones...
BUT the dynamic bindings have the big advantage that you don't need to compile anything to install.
See test_dynamic.py for how to use them.

View file

@ -9,7 +9,7 @@
# *
# ********************************************************************************************/
from raylib import *
from raylib.static import *
# Initialization

View file

@ -9,7 +9,7 @@
# *
# ********************************************************************************************/
from raylib import *
from raylib.static import *
# Initialization
# --------------------------------------------------------------------------------------

View file

@ -9,7 +9,7 @@
# *
# ********************************************************************************************/
from raylib import *
from raylib.static import *
# Initialization

View file

@ -1,80 +0,0 @@
/*******************************************************************************************
*
* raylib [models] example - Draw some basic geometric shapes (cube, sphere, cylinder...)
*
* This example has been created using raylib 1.0 (www.raylib.com)
* raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
*
* Copyright (c) 2014 Ramon Santamaria (@raysan5)
*
********************************************************************************************/
#include "raylib.h"
int main()
[
# Initialization
#--------------------------------------------------------------------------------------
int screenWidth = 800
int screenHeight = 450
InitWindow(screenWidth, screenHeight, "raylib [models] example - geometric shapes")
# Define the camera to look into our 3d world
Camera camera = [ 0 ]
camera.position = (Vector3)[ 0.0, 10.0, 10.0 ]
camera.target = (Vector3)[ 0.0, 0.0, 0.0 ]
camera.up = (Vector3)[ 0.0, 1.0, 0.0 ]
camera.fovy = 45.0
camera.type = CAMERA_PERSPECTIVE
SetTargetFPS(60) # Set our game to run at 60 frames-per-second
#--------------------------------------------------------------------------------------
# Main game loop
while (!WindowShouldClose()) # Detect window close button or ESC key
[
# Update
#----------------------------------------------------------------------------------
# TODO: Update your variables here
#----------------------------------------------------------------------------------
# Draw
#----------------------------------------------------------------------------------
BeginDrawing()
ClearBackground(RAYWHITE)
BeginMode3D(camera)
DrawCube((Vector3)[-4.0, 0.0, 2.0], 2.0, 5.0, 2.0, RED)
DrawCubeWires((Vector3)[-4.0, 0.0, 2.0], 2.0, 5.0, 2.0, GOLD)
DrawCubeWires((Vector3)[-4.0, 0.0, -2.0], 3.0, 6.0, 2.0, MAROON)
DrawSphere((Vector3)[-1.0, 0.0, -2.0], 1.0, GREEN)
DrawSphereWires((Vector3)[1.0, 0.0, 2.0], 2.0, 16, 16, LIME)
DrawCylinder((Vector3)[4.0, 0.0, -2.0], 1.0, 2.0, 3.0, 4, SKYBLUE)
DrawCylinderWires((Vector3)[4.0, 0.0, -2.0], 1.0, 2.0, 3.0, 4, DARKBLUE)
DrawCylinderWires((Vector3)[4.5f, -1.0, 2.0], 1.0, 1.0, 2.0, 6, BROWN)
DrawCylinder((Vector3)[1.0, 0.0, -4.0], 0.0, 1.5f, 3.0, 8, GOLD)
DrawCylinderWires((Vector3)[1.0, 0.0, -4.0], 0.0, 1.5f, 3.0, 8, PINK)
DrawGrid(10, 1.0) # Draw a grid
EndMode3D()
DrawFPS(10, 10)
EndDrawing()
#----------------------------------------------------------------------------------
]
# De-Initialization
#--------------------------------------------------------------------------------------
CloseWindow() # Close window and OpenGL context
#--------------------------------------------------------------------------------------
return 0
]

View file

@ -0,0 +1,76 @@
# /*******************************************************************************************
# *
# * raylib [models] example - Draw some basic geometric shapes (cube, sphere, cylinder...)
# *
# * This example has been created using raylib 1.0 (www.raylib.com)
# * raylib is licensed under an unmodified zlib/libpng license (View raylib.h for details)
# *
# * Copyright (c) 2014 Ramon Santamaria (@raysan5)
# *
# ********************************************************************************************/
from raylib.static import *
# Initialization
#--------------------------------------------------------------------------------------
screenWidth = 800
screenHeight = 450
InitWindow(screenWidth, screenHeight, b"raylib [models] example - geometric shapes")
# Define the camera to look into our 3d world
cameraPtr = ffi.new("struct Camera3D *")
camera = cameraPtr[0]
camera.position = [ 0.0, 10.0, 10.0 ]
camera.target = [ 0.0, 0.0, 0.0 ]
camera.up = [ 0.0, 1.0, 0.0 ]
camera.fovy = 45.0
camera.type = CAMERA_PERSPECTIVE
SetTargetFPS(60) # Set our game to run at 60 frames-per-second
#--------------------------------------------------------------------------------------
# Main game loop
while not WindowShouldClose(): # Detect window close button or ESC key
# Update
#----------------------------------------------------------------------------------
# TODO: Update your variables here
#----------------------------------------------------------------------------------
# Draw
#----------------------------------------------------------------------------------
BeginDrawing()
ClearBackground(RAYWHITE)
BeginMode3D(camera)
DrawCube([-4.0, 0.0, 2.0], 2.0, 5.0, 2.0, RED)
DrawCubeWires([-4.0, 0.0, 2.0], 2.0, 5.0, 2.0, GOLD)
DrawCubeWires([-4.0, 0.0, -2.0], 3.0, 6.0, 2.0, MAROON)
DrawSphere([-1.0, 0.0, -2.0], 1.0, GREEN)
DrawSphereWires([1.0, 0.0, 2.0], 2.0, 16, 16, LIME)
DrawCylinder([4.0, 0.0, -2.0], 1.0, 2.0, 3.0, 4, SKYBLUE)
DrawCylinderWires([4.0, 0.0, -2.0], 1.0, 2.0, 3.0, 4, DARKBLUE)
DrawCylinderWires([4.5, -1.0, 2.0], 1.0, 1.0, 2.0, 6, BROWN)
DrawCylinder([1.0, 0.0, -4.0], 0.0, 1.5, 3.0, 8, GOLD)
DrawCylinderWires([1.0, 0.0, -4.0], 0.0, 1.5, 3.0, 8, PINK)
DrawGrid(10, 1.0) # Draw a grid
EndMode3D()
DrawFPS(10, 10)
EndDrawing()
#----------------------------------------------------------------------------------
# De-Initialization
#--------------------------------------------------------------------------------------
CloseWindow() # Close window and OpenGL context
#--------------------------------------------------------------------------------------

View file

@ -9,7 +9,7 @@
# *
# ********************************************************************************************/
from raylib import *
from raylib.static import *
# Initialization
#--------------------------------------------------------------------------------------

View file

@ -1,10 +1 @@
__version__ = "2.5.dev3"
from ._raylib_cffi import ffi, lib as rl
from _raylib_cffi.lib import *
from .colors import *
from .helpers import *
__version__ = "2.5.dev4"

View file

@ -0,0 +1,38 @@
"""
This is an attempt at a CFFI dynamic (ABI) binding. It was failing in the exactly same place the ctypes binding fails, accessing
materials of a model. But now it __seems__ to work
"""
import platform
# Probably unnecessary, just covering all bases in case people add or remove dlls
MAC_NAMES = ['libraylib.2.5.0.dylib', 'libraylib.2.dylib', 'libraylib.dylib']
LINUX_NAMES = ['libraylib.so.2.5.0','libraylib.so.2', 'libraylib.so']
WINDOWS_NAMES = ['libraylib.dll', 'raylib.dll']
if platform.system() == "Darwin":
NAMES_TO_TRY = MAC_NAMES
elif platform.system() == "Linux":
NAMES_TO_TRY = LINUX_NAMES
elif platform.system() == "Windows":
NAMES_TO_TRY = WINDOWS_NAMES
else:
NAMES_TO_TRY = MAC_NAMES + LINUX_NAMES + WINDOWS_NAMES
import pathlib
MODULE = pathlib.Path(__file__).parent.parent
from cffi import FFI
ffi = FFI()
ffi.cdef(open(MODULE / "raylib_modified.h").read().replace('RLAPI ', ''))
for name in NAMES_TO_TRY:
file = str(MODULE)+"/dynamic/"+name
try:
raylib = ffi.dlopen(file)
print("LOADED DYNAMICALLY SHARED LIB "+file)
break
except Exception as e:
print(e)

Binary file not shown.

View file

@ -0,0 +1 @@
libraylib.2.5.0.dylib

Binary file not shown.

View file

@ -1,15 +0,0 @@
"""
This is an attempt at a CFFI dynamic (ABI) binding. However, it fails to work in the exactly same place the ctypes binding fails, accessing
materials of a model.
"""
import pathlib
MODULE = pathlib.Path(__file__).parent.parent
from cffi import FFI
ffi = FFI()
ffi.cdef(open(MODULE / "raylib_modified.h").read().replace('RLAPI ', ''))
raylib = ffi.dlopen(str(MODULE)+"/dynamic_binding/libraylib.2.dylib")

View file

@ -0,0 +1,8 @@
from ._raylib_cffi import ffi, lib as rl
from _raylib_cffi.lib import *
from raylib.colors import *
from .helpers import *
print("RAYLIB STATIC LOADED")

View file

@ -490,7 +490,7 @@ static void (*_cffi_call_python_org)(struct _cffi_externpy_s *, char *);
/************************************************************/
#include "raylib.h" // the C header of the library
#include "../raylib.h" // the C header of the library
/************************************************************/

View file

@ -6,12 +6,12 @@ import platform
ffibuilder = FFI()
ffibuilder.cdef(open("raylib_modified.h").read().replace('RLAPI ', ''))
ffibuilder.cdef(open("../raylib_modified.h").read().replace('RLAPI ', ''))
ffibuilder.set_source("_raylib_cffi",
"""
#include "raylib.h" // the C header of the library
#include "raylib.h" // the C header, installed in the system include dir we assume
""",
#library_dirs=['/Volumes/Home/rich/raylib-latest/src'],
# extra_link_args=['-Wl,-rpath,.'],

View file

@ -4,16 +4,16 @@ import platform
ffibuilder = FFI()
ffibuilder.cdef(open("raylib_modified.h").read().replace('RLAPI ', ''))
ffibuilder.cdef(open("../raylib_modified.h").read().replace('RLAPI ', ''))
ffibuilder.set_source("_raylib_cffi",
"""
#include "raylib.h" // the C header of the library
#include "../raylib.h" // the C header of the library, supplied by us here
"""
)
# Hack to produce static linked lib
# Hack to produce static linked lib using static librarylib.a supplied by us
command = "clang -bundle -undefined dynamic_lookup ./_raylib_cffi.o -L/usr/local/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/sqlite/lib libraylib.a -F/System/Library/Frameworks -framework OpenGL -framework Cocoa -framework IOKit -framework CoreFoundation -framework CoreVideo -o ./_raylib_cffi.cpython-37m-darwin.so"
if __name__ == "__main__":

View file

@ -3,10 +3,10 @@
from cffi import FFI
ffibuilder = FFI()
ffibuilder.cdef(open("raylib_modified.h").read().replace('RLAPI ', ''))
ffibuilder.cdef(open("../raylib_modified.h").read().replace('RLAPI ', ''))
ffibuilder.set_source("_raylib_cffi",
"""
#include "raylib.h" // the C header of the library
#include "raylib.h" // THIS MIGHT NEED TO BE CHANGED TO "../raylib.h" IF RAYLIB HEADERS NOT FOUND
""",
extra_link_args=['/NODEFAULTLIB:MSVCRTD'],
libraries=['raylib', 'gdi32', 'shell32', 'user32','OpenGL32', 'winmm'],

View file

@ -10,7 +10,7 @@ README = (HERE / "README.md").read_text()
# This call to setup() does all the work
setup(
name="raylib",
version="2.5.dev4",
version="2.5.dev5",
description="Python CFFI bindings for Raylib",
long_description=README,
long_description_content_type="text/markdown",
@ -23,7 +23,7 @@ setup(
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.7",
],
packages=["raylib"],
packages=["raylib", "raylib.dynamic", "raylib.static"],
include_package_data=True,
install_requires=["cffi"],
#cffi_modules=["raylib/build_mac.py:ffibuilder"], # this would build libs whenever the module is installed, but we are distributing static libs instead

View file

@ -1,42 +1,31 @@
"""
This is an attempt at a CFFI dynamic (ABI) binding. However, it fails to work in the same place the ctypes binding fails, accessing
materials of a model, because Python can't dynamically tell the difference between a pointer and an array. There's probably
some way to specify this (e.g. in raylib_modified.h) but it's difficult to be sure we fixed them all, and the errors
are often completely silent.
This shows how to use the CFFI dynamic (ABI) binding. Note that is slower and more likely to run into silent errors.
But it doesnt require any C compiler to build.
"""
import pathlib
MODULE = pathlib.Path(__file__).parent
print(MODULE)
from raylib.dynamic_binding import ffi, raylib as rl
from raylib.dynamic import ffi, raylib as rl
from raylib.colors import *
rl.InitWindow(800,450,b"foo")
rl.InitWindow(800,450,b"Raylib dynamic binding test")
rl.SetTargetFPS(60)
camera = ffi.new("struct Camera3D *", [[ 18.0, 16.0, 18.0 ], [ 0.0, 0.0, 0.0 ], [ 0.0, 1.0, 0.0 ], 45.0, 0 ])
imageFile = str(MODULE / "examples/models/resources/heightmap.png").encode('utf-8')
image = rl.LoadImage(imageFile) # Load heightmap image (RAM)
print(image)
texture = rl.LoadTextureFromImage(image) # Convert image to texture (VRAM)
image = rl.LoadImage(imageFile)
texture = rl.LoadTextureFromImage(image)
mesh = rl.GenMeshHeightmap(image, [ 16, 8, 16 ])
model = rl.LoadModelFromMesh(mesh)
print(model.materials) # SHOULD BE A pointer to a 'struct Material' but some is NULL pointer to 'Material' ?
mesh = rl.GenMeshHeightmap(image, [ 16, 8, 16 ]) # Generate heightmap mesh (RAM and VRAM)
model.materials[0].maps[rl.MAP_DIFFUSE].texture = texture
mapPosition = ( -8.0, 0.0, -8.0 )
print(mesh)
rl.UnloadImage(image)
model = rl.LoadModelFromMesh(mesh) # Load model from generated mesh
print(model.materials) # SHOULD BE A pointer to a 'struct Material' but instead is NULL pointer to 'Material'
#model.materials[0].maps[rl.MAP_DIFFUSE].texture = texture # Set map diffuse texture
mapPosition = ( -8.0, 0.0, -8.0 ) # Define model position
rl.UnloadImage(image) # Unload heightmap image from RAM, already uploaded to VRAM
rl.SetCameraMode(camera[0], rl.CAMERA_ORBITAL) # Set an orbital camera mode
rl.SetCameraMode(camera[0], rl.CAMERA_ORBITAL)
while not rl.WindowShouldClose():
@ -47,6 +36,12 @@ while not rl.WindowShouldClose():
rl.DrawModel(model, mapPosition, 1.0, RED)
rl.DrawGrid(20, 1.0)
rl.EndMode3D()
rl.DrawText(b"sdfsdf", 190, 200, 20, BLACK)
rl.DrawText(b"This mesh should be textured", 190, 200, 20, VIOLET)
rl.EndDrawing()
rl.CloseWindow()
rl.CloseWindow()
"""
Previously this failed to work in the same place the ctypes binding fails, accessing
materials of a model. I though it was because Python can't dynamically tell the difference between a pointer and an array.
"""

View file

@ -1,7 +1,7 @@
from raylib import *
from raylib.static import *
InitWindow(800,450,b"foo")
InitWindow(800,450,b"Raylib texture test")
SetTargetFPS(60)
print(Vector3(1,1,1))
@ -10,15 +10,24 @@ camera = ffi.new("struct Camera3D *", [[ 18.0, 16.0, 18.0 ], [ 0.0, 0.0, 0.0 ],
image = LoadImage(b"examples/models/resources/heightmap.png") # Load heightmap image (RAM)
print(image)
texture = LoadTextureFromImage(image) # Convert image to texture (VRAM)
mesh = GenMeshHeightmap(image, ( 16, 8, 16 )) # Generate heightmap mesh (RAM and VRAM)
print(mesh)
model = LoadModelFromMesh(mesh) # Load model from generated mesh
print(model.meshes)
print(model.meshes[1])
print(model.materials)
print(model.materialCount)
print(model.materials[0].maps[rl.MAP_DIFFUSE])
model.materials[0].maps[MAP_DIFFUSE].texture = texture # Set map diffuse texture
print(model.materials[0].maps[rl.MAP_DIFFUSE].value)
mapPosition = ( -8.0, 0.0, -8.0 ) # Define model position
UnloadImage(image) # Unload heightmap image from RAM, already uploaded to VRAM
@ -34,6 +43,6 @@ while not WindowShouldClose():
DrawModel(model, mapPosition, 1.0, RED)
DrawGrid(20, 1.0)
EndMode3D()
DrawText(b"sdfsdf", 190, 200, 20, BLACK)
DrawText(b"This mesh should be textured", 190, 200, 20, VIOLET)
EndDrawing()
CloseWindow()