Skip to content

How to hack the cfwrapper

vmagnin edited this page Apr 11, 2023 · 5 revisions

This guide shows you how to hack the gtk-fortran cfwrapper to try generating interfaces for other C libraries.

Requirements

This was tested in a Linux Ubuntu system and should work with other Unix-like systems. Although Python 3 is cross-platform, I have not tried the cfwrapper script on Windows and you may encounter for example directory paths problems (tell me your experience).

Steps

Prepare the directories and files

If you have a GitHub account, just clone the gtk-fortran repository and go into the cfwrapper directory:

$ git clone [email protected]:vmagnin/gtk-fortran.git
$ cd gtk-fortran/src/cfwrapper/

In a Unix-like system, the header files .h of the C libraries are generally in a subdirectory in the /usr/include/ directory. But you can also make a subdirectory other/ in the directory of the wrapper and put your header files there.

Launch the cfwrapper

You must use both -l and -m option to respectively add the directories containing the header files and the corresponding Fortran modules names. All the interfaces generated for .h files in a directory (and its subdirectories) will be put in the same Fortran module in a modulename-auto.f90 file, in the parent src/ directory.

$ ./cfwrapper.py -l /usr/include/libsoup-3.0 /usr/include/json-glib-1.0 -m libsoup json
 Pass 1: looking for enumerators, funptr and derived types...
 Pass 2: looking for C functions... 
/usr/include/libsoup-3.0         =>  libsoup-auto.f90        125042 bytes
/usr/include/json-glib-1.0       =>  json-auto.f90            66359 bytes

Extracting GDK events for gtk-0-fortran
Failed to open /usr/include/gtk-0.0/gdk/gdktypes.h:No such file or directory

=== Statistics (ready to paste in the Status wiki page) ===

## gtk-fortran 0.0.0, GTK not_GTK, GLib 2.74.3, Ubuntu 22.10 x86_64, Python 3.10.7
vmagnin, Sun, 09 Apr 2023 09:50:07 +0000
* nb_files scanned =            55
* nb_generated_interfaces =    590
* nb_deprecated_functions =      5
* nb_type_errors =              50
* nb_errors (others) =          38
* nb_lines treated =          1884
* nb_variadic functions =        6
* nb_enumerators =              27
* nb_win32_utf8 =                0
* Number of types =             65
* Number of funptr types =      13
* Computing time: 0.34 s
* SHA1:  60dfe48b11ea511bb3b85197181994117f71d5e0
 >>>>>> SHA 1 HAS BEEN MODIFIED ! It was  10067b0d918677d31b4c9bc9c70a7a3ca27bc29a  <<<<<< 


 Used types: ['c_ptr', 'c_int', 'c_char', 'c_funptr', '?', 'c_size_t', 'c_long', 'c_int64_t', 'c_double']

In the parent directory src/, you will find the generated libsoup-auto.f90 and json-auto.f90 files. The list of the generated interfaces are in gtk-fortran-index.csv. The potential enums will be in other_enums-auto.f90: in gtk-fortran this file is included into another file, so you will need to add the module...end module, use... and implicit none statements.

In the directory of the cfwrapper, you will also find a cfwrapper-errors.csv file, useful to understand the problems encountered by the wrapper.

Verify and test

Disclaimer of Warranty: don't trust blindly the cfwrapper, you are the developer. Look at your interfaces: do they look OK? Are there missing interfaces or enums?

Copy the Fortran modules into your project and test some of its functions. You may be interested in the page Fortran interoperability with C of this wiki.

Feel free to distribute your interfaces with any license. Acknowledging you used the cfwrapper is of course welcomed :-)

Issues

Fortranauts: "Okay, Houston, we've had a problem here"

Houston: "Well, it's just a hack, don't expect full support dudes!"

Fortranauts: "...?"

More seriously, if you have a problem, you can post an Issue here or in the Fortran Discourse. I will try to guide you and help if possible.

If your header files are "clean" (no C preprocessor directives and macros, just standard C types...), you can expect a good result and maybe a perfect one!

If a C data type is not recognized, the prototype will be discarded. Edit the file scan_types_and_enums.py. At its top you will find a dictionary containing the Fortran type and its KIND for each C type:

TYPES_DICT = {
        "int":("integer(c_int)", "c_int"),
        "gint":("integer(c_int)", "c_int"),
        "guint":("integer(c_int)", "c_int"),

Just add the missing type following the same model and relaunch the cfwrapper.

If your header files are full of C preprocessor directives and macros, you could have more difficulties. You may have to hack the regular expressions of the cfwrapper, especially in cleaning.py which is removing comments and preprocessor stuff in the header files, and analyze.py which is analyzing the C prototypes.

Other tricks

If for any reason you prefer that the Fortran interfaces have not exactly the same names as the C functions, you can use the -s (--suffix) option to add a suffix to the functions names, for example:

$ ./cfwrapper.py -l /usr/include/libsoup-3.0 -m libsoup -s _f

will produce interfaces like:

function soup_message_new_f(method, uri_string) bind(c, name="soup_message_new")
...

instead of:

function soup_message_new(method, uri_string) bind(c)
...
Clone this wiki locally