1. Wrapping Functions Inside of Struct?
- Posted by Icy_Viking Oct 10, 2022
- 803 views
Hi all,
I'm just wondering if there's a way to wrap functions that are in a struct or is there some other work-a-round?
//header file "file.h" from Allegro typedef struct ALLEGRO_FILE_INTERFACE { AL_METHOD(void *, fi_fopen, (const char *path, const char *mode)); AL_METHOD(bool, fi_fclose, (ALLEGRO_FILE *handle)); AL_METHOD(size_t, fi_fread, (ALLEGRO_FILE *f, void *ptr, size_t size)); AL_METHOD(size_t, fi_fwrite, (ALLEGRO_FILE *f, const void *ptr, size_t size)); AL_METHOD(bool, fi_fflush, (ALLEGRO_FILE *f)); AL_METHOD(int64_t, fi_ftell, (ALLEGRO_FILE *f)); AL_METHOD(bool, fi_fseek, (ALLEGRO_FILE *f, int64_t offset, int whence)); AL_METHOD(bool, fi_feof, (ALLEGRO_FILE *f)); AL_METHOD(int, fi_ferror, (ALLEGRO_FILE *f)); AL_METHOD(const char *, fi_ferrmsg, (ALLEGRO_FILE *f)); AL_METHOD(void, fi_fclearerr, (ALLEGRO_FILE *f)); AL_METHOD(int, fi_fungetc, (ALLEGRO_FILE *f, int c)); AL_METHOD(off_t, fi_fsize, (ALLEGRO_FILE *f)); } ALLEGRO_FILE_INTERFACE;
My vague idea would be
include std/ffi.e public constant ALLEGRO_FILE_INTERFACE = define_c_type({ C_STRING, --path C_STRING --mode }) OR --I feel like this wouldn't work, but its an idea I had. public constant ALLEGRO_FILE_INTERFACE = define_c_type({ atom x = define_c_proc(all,"+fi_open",{C_STRING,C_STRING}) public procedure fi_open(sequence path,sequence mode) c_proc(x,{path,mode}) end procedure })
2. Re: Wrapping Functions Inside of Struct?
- Posted by petelomax Oct 11, 2022
- 763 views
I could be wrong, but from what I can see, if you're not using al_fopen() then you don't need ALLEGRO_FILE_INTERFACE.
If you have a working example using al_fopen() that does not use al_set_new_file_interface() then you don't need "".
Should you actually need it, then al_set_new_file_interface() just needs a (carefully ordered) bank of 13 call_backs().
There would be very little benefit, and perhaps possibility for misuse, for your app itself to know about any function
names/args/return types, that is, after they've been put into, or in getting back out of, such a simple flat array.
HTH, Pete
3. Re: Wrapping Functions Inside of Struct?
- Posted by ghaberek (admin) Oct 11, 2022
- 766 views
I'm just wondering if there's a way to wrap functions that are in a struct or is there some other work-a-round?
I could be wrong, but from what I can see, if you're not using al_fopen() then you don't need ALLEGRO_FILE_INTERFACE.
If you have a working example using al_fopen() that does not use al_set_new_file_interface() then you don't need "".
Should you actually need it, then al_set_new_file_interface() just needs a (carefully ordered) bank of 13 call_backs().
There would be very little benefit, and perhaps possibility for misuse, for your app itself to know about any function
names/args/return types, that is, after they've been put into, or in getting back out of, such a simple flat array.
Pete's right; these are just callbacks for creating a custom file interface. It's possible you might want to do this if, for example, you wanted to store your resources in a single archive and access each entry using the Allegro file functions.
The AL_METHOD macro is defined in internal/alconfig.h
#define AL_METHOD(type, name, args) type (*name) args
So an entry like this:
AL_METHOD(void *, fi_fopen, (const char *path, const char *mode));
Just gets translated to this:
void *(*fi_fopen)(const char *path, const char *mode);
Which is just a function pointer.
So your structure definition would look like this:
export constant AL_ALLEGRO_FILE_INTERFACE = define_c_type({ C_POINTER, -- void *(*fi_fopen)(const char *path, const char *mode); C_POINTER, -- bool (*fi_fclose)(ALLEGRO_FILE *handle); C_POINTER, -- size_t (*fi_fread)(ALLEGRO_FILE *f, void *ptr, size_t size); C_POINTER, -- size_t (*fi_fwrite)(ALLEGRO_FILE *f, const void *ptr, size_t size); C_POINTER, -- bool (*fi_fflush)(ALLEGRO_FILE *f); C_POINTER, -- int64_t (*fi_ftell)(ALLEGRO_FILE *f); C_POINTER, -- bool (*fi_fseek)(ALLEGRO_FILE *f, int64_t offset, int whence); C_POINTER, -- bool (*fi_feof)(ALLEGRO_FILE *f); C_POINTER, -- int (*fi_ferror)(ALLEGRO_FILE *f); C_POINTER, -- const char *(*fi_ferrmsg)(ALLEGRO_FILE *f); C_POINTER, -- void (*fi_fclearerr)(ALLEGRO_FILE *f); C_POINTER, -- int (*fi_fungetc)(ALLEGRO_FILE *f, int c); C_POINTER -- off_t (*fi_fsize)(ALLEGRO_FILE *f); })
And your custom interface implementation might look something like this:
function fi_fopen( sequence path, sequence mode ) return 0 end function function fi_fclose( atom handle ) return 0 end function function fi_fread( atom f, atom ptr, atom size ) return 0 end function function fi_fwrite( atom f, atom ptr, atom size ) return 0 end function function fi_fflush( atom f ) return 0 end function function fi_ftell( atom f ) return 0 end function function fi_fseek( atom f, atom offset, atom whence ) return 0 end function function fi_feof( atom f ) return 0 end function function fi_ferror( atom f ) return 0 end function function fi_ferrmsg( atom f ) return 0 end function function fi_fclearerr( atom f ) return 0 end function function fi_fungetc( atom f, integer c ) return 0 end function function fi_fsize( atom f ) return 0 end function constant C_OFF_T = C_LONG_PTR -- used by fi_fsize() constant MY_INTERFACE = allocate_struct( AL_ALLEGRO_FILE_INTERFACE, { call_back( routine_id("fi_fopen"), {C_STRING,C_STRING}, C_POINTER ), call_back( routine_id("fi_fclose"), {C_POINTER}, C_BOOL ), call_back( routine_id("fi_fread"), {C_POINTER,C_POINTER,C_SIZE_T}, C_SIZE_T ), call_back( routine_id("fi_fwrite"), {C_POINTER,C_POINTER,C_SIZE_T}, C_SIZE_T ), call_back( routine_id("fi_fflush"), {C_POINTER}, C_BOOL ), call_back( routine_id("fi_ftell"), {C_POINTER}, C_INT64 ), call_back( routine_id("fi_fseek"), {C_POINTER,C_INT64,C_INT}, C_BOOL ), call_back( routine_id("fi_feof"), {C_POINTER}, C_BOOL ), call_back( routine_id("fi_ferror"), {C_POINTER}, C_INT ), call_back( routine_id("fi_ferrmsg"), {C_POINTER}, C_POINTER ), call_back( routine_id("fi_fclearerr"), {C_POINTER}, C_VOID ), call_back( routine_id("fi_fungetc"), {C_POINTER,C_INT}, C_INT ), call_back( routine_id("fi_fsize"), {C_POINTER}, C_OFF_T ) })
And then you'd use it like this:
atom f = al_fopen_interface( MY_INTERFACE, "path/to/myfile.ext", "r" ) -- do file things here al_fclose( f )
-Greg
4. Re: Wrapping Functions Inside of Struct?
- Posted by Icy_Viking Oct 11, 2022
- 748 views
I'm just wondering if there's a way to wrap functions that are in a struct or is there some other work-a-round?
I could be wrong, but from what I can see, if you're not using al_fopen() then you don't need ALLEGRO_FILE_INTERFACE.
If you have a working example using al_fopen() that does not use al_set_new_file_interface() then you don't need "".
Should you actually need it, then al_set_new_file_interface() just needs a (carefully ordered) bank of 13 call_backs().
There would be very little benefit, and perhaps possibility for misuse, for your app itself to know about any function
names/args/return types, that is, after they've been put into, or in getting back out of, such a simple flat array.
Pete's right; these are just callbacks for creating a custom file interface. It's possible you might want to do this if, for example, you wanted to store your resources in a single archive and access each entry using the Allegro file functions.
The AL_METHOD macro is defined in internal/alconfig.h
#define AL_METHOD(type, name, args) type (*name) args
So an entry like this:
AL_METHOD(void *, fi_fopen, (const char *path, const char *mode));
Just gets translated to this:
void *(*fi_fopen)(const char *path, const char *mode);
Which is just a function pointer.
So your structure definition would look like this:
export constant AL_ALLEGRO_FILE_INTERFACE = define_c_type({ C_POINTER, -- void *(*fi_fopen)(const char *path, const char *mode); C_POINTER, -- bool (*fi_fclose)(ALLEGRO_FILE *handle); C_POINTER, -- size_t (*fi_fread)(ALLEGRO_FILE *f, void *ptr, size_t size); C_POINTER, -- size_t (*fi_fwrite)(ALLEGRO_FILE *f, const void *ptr, size_t size); C_POINTER, -- bool (*fi_fflush)(ALLEGRO_FILE *f); C_POINTER, -- int64_t (*fi_ftell)(ALLEGRO_FILE *f); C_POINTER, -- bool (*fi_fseek)(ALLEGRO_FILE *f, int64_t offset, int whence); C_POINTER, -- bool (*fi_feof)(ALLEGRO_FILE *f); C_POINTER, -- int (*fi_ferror)(ALLEGRO_FILE *f); C_POINTER, -- const char *(*fi_ferrmsg)(ALLEGRO_FILE *f); C_POINTER, -- void (*fi_fclearerr)(ALLEGRO_FILE *f); C_POINTER, -- int (*fi_fungetc)(ALLEGRO_FILE *f, int c); C_POINTER -- off_t (*fi_fsize)(ALLEGRO_FILE *f); })
And your custom interface implementation might look something like this:
function fi_fopen( sequence path, sequence mode ) return 0 end function function fi_fclose( atom handle ) return 0 end function function fi_fread( atom f, atom ptr, atom size ) return 0 end function function fi_fwrite( atom f, atom ptr, atom size ) return 0 end function function fi_fflush( atom f ) return 0 end function function fi_ftell( atom f ) return 0 end function function fi_fseek( atom f, atom offset, atom whence ) return 0 end function function fi_feof( atom f ) return 0 end function function fi_ferror( atom f ) return 0 end function function fi_ferrmsg( atom f ) return 0 end function function fi_fclearerr( atom f ) return 0 end function function fi_fungetc( atom f, integer c ) return 0 end function function fi_fsize( atom f ) return 0 end function constant C_OFF_T = C_LONG_PTR -- used by fi_fsize() constant MY_INTERFACE = allocate_struct( AL_ALLEGRO_FILE_INTERFACE, { call_back( routine_id("fi_fopen"), {C_STRING,C_STRING}, C_POINTER ), call_back( routine_id("fi_fclose"), {C_POINTER}, C_BOOL ), call_back( routine_id("fi_fread"), {C_POINTER,C_POINTER,C_SIZE_T}, C_SIZE_T ), call_back( routine_id("fi_fwrite"), {C_POINTER,C_POINTER,C_SIZE_T}, C_SIZE_T ), call_back( routine_id("fi_fflush"), {C_POINTER}, C_BOOL ), call_back( routine_id("fi_ftell"), {C_POINTER}, C_INT64 ), call_back( routine_id("fi_fseek"), {C_POINTER,C_INT64,C_INT}, C_BOOL ), call_back( routine_id("fi_feof"), {C_POINTER}, C_BOOL ), call_back( routine_id("fi_ferror"), {C_POINTER}, C_INT ), call_back( routine_id("fi_ferrmsg"), {C_POINTER}, C_POINTER ), call_back( routine_id("fi_fclearerr"), {C_POINTER}, C_VOID ), call_back( routine_id("fi_fungetc"), {C_POINTER,C_INT}, C_INT ), call_back( routine_id("fi_fsize"), {C_POINTER}, C_OFF_T ) })
And then you'd use it like this:
atom f = al_fopen_interface( MY_INTERFACE, "path/to/myfile.ext", "r" ) -- do file things here al_fclose( f )
-Greg
Thanks Greg, that makes a lot of sense. It was simpler then I had previously thought.