Re: Allegro Wrapper Concerns
- Posted by ghaberek (admin) Oct 10, 2022
- 598 views
Hi all,
As I am starting on wrapping an allegro wrapper using the new ffi.e, I have come across a few issues that are sorta bothersome, but not a huge deal in the grand scheme of things. Though I was wondering if anyone had any thoughts on this. I want to keep the allegro as close to the C source as possible. For example color.h would be color.e and contain the functions found in color.h, but of course wrapped as Euphoria functions.
...snip...
AS you can see, I can keep the flags in the color.e, but ideally I would like to have the functions in there too. When I tried to run it, I got an error saying the 'all' variable could not be found. So I put the color functions in the main allegro.e and it worked. If there's any tips or tricks I can use, I'd sure like to know them.
Try (just for the sake of elimination and experimentation) defining 'all' before including color.e
This is a good example of how to the scoping rules work in Euphoria and why we have both export and public. There are technically twelve scopes inside the interpreter but we're only concerned with four:
Keyword | Description |
---|---|
none | local to the file |
global | global across all files |
export | visible to anyone that includes the file |
public | visible to any file that includes it, or via "public include" |
You can't see export constant all because you're not including base.e in color.e. The behavior you're expecting is produced by global which is technically deprecated.
The best practice here would be to use public for symbols required for using the API like al_get_allegro_version() and use export for symbols required for implementing the API like the constants created by define_c_func(), etc.
To put it another way, anything the end-programmer needs to see should be public and anything the library-wrapping programmer needs to see should be export. I hope that makes sense.
That being said, I recommend simply following the existing file hierarchy already established by Allegro using public include in allegro5/allegro.e:
include/allegro5/allegro.e
namespace allegro public include allegro5/base.e public include allegro5/color.e -- etc.
And then put your open_dll() in base.e and segment your define_c_func/proc constants into their respective files:
include/allegro5/base.e
namespace allegro_base include std/ffi.e include std/machine.e -- export scope is only available to files that directly include this file so this won't -- be available if you only include allegro5/allegro.e (which is what we want anyway) export constant liballeg = open_dll( "allegro-5.2.dll" ), _al_get_allegro_version = define_c_func( liballeg, "+al_get_allegro_version", {}, C_UINT ) -- "public" scope is available to files including this file or any file that "public includes" this file public function al_get_allegro_version() return c_func( _al_get_allegro_version, {} ) end function
include/allegro5/color.e
namespace allegro_color include std/ffi.e include std/machine.e include allegro5/base.e -- provides exported constant liballeg export constant AL_ALLEGRO_COLOR = define_c_type({ C_FLOAT, -- r C_FLOAT, -- g C_FLOAT, -- b C_FLOAT -- a }) export constant _al_map_rgb = define_c_func( liballeg, "+al_map_rgb", {C_UCHAR,C_UCHAR,C_UCHAR}, AL_ALLEGRO_COLOR ), _al_map_rgba = define_c_func( liballeg, "+al_map_rgba", {C_UCHAR,C_UCHAR,C_UCHAR,C_UCHAR}, AL_ALLEGRO_COLOR ) public function al_map_rgb( integer r, integer g, integer b ) return c_func( _al_map_rgb, {r,g,b} ) end function public function al_map_rgba( integer r, integer g, integer b, integer a ) return c_func( _al_map_rgba, {r,g,b,a} ) end function
-Greg