collapse Table of Contents
  1. Announcing Mono.Fuse - Jonathan Pryor's web log
    1. Announcing Mono.Fuse
      1. Why?
      2. What about SULF?
      3. Implementation
        1. mono
        2. mcs
      4. HOWTO
      5. Questions

Announcing Mono.Fuse - Jonathan Pryor's web log

« Definitions Matter | Main | Mono.Fuse, Take 2.1! »

Announcing Mono.Fuse

Mono.Fuse is a binding for the FUSE library, permitting user-space file systems to be written in C#.


I read Robert Love's announcement of beaglefs, a FUSE program that exposes Beagle searches as a filesystem. My first thought: Why wasn't that done in C# (considering that the rest of Beagle is C#)?

What about SULF?

Stackable User-Level Filesystem, or SULF, is a pre-existing FUSE binding in C#, started by Valient Gough in 2004.

Mono.Fuse has no relation to SULF, for three reasons:

  1. It goes to great efforts to avoid a Mono.Posix.dll dependency, duplicating Mono.Unix.Native.Stat (Fuse.Stat), Mono.Unix.Native.Statvfs (Fuse.StatFS), and many methods from Mono.Unix.Native.Syscall (Fuse.Wrapper).
  2. I don't like the SULF API. (Not that I spent a great deal of time looking at it, but what I did see I didn't like.)
  3. SULF wraps the FUSE kernel-level interface, while Mono.Fuse wraps the higher level libfuse C interface.

I find (1) the most appalling, if only because I'm the Mono.Posix maintainer and I'd like to see my work actually used. :-)

Once I started writing Mono.Fuse, I discovered a good reason to avoid Mono.Posix: it's currently impossible to use the native MonoPosixHelper shared library from outside of Mono. I figured this would be a good opportunity to rectify that, making it easier for additional libraries to build upon the Mono.Posix infrastructure.


Mono.Fuse requires patches to the mcs and mono modules, changes which need to be proposed and discussed.


The biggest problem with the mono module is that no headers are installed, making it difficult to make use of


map.h is the current map.h file generated by make-map.exe, with some major additions (detailed in the mcs section).

helper.h is the main include file, which includes map.h and declares all types/functions which cannot be generated by make-map.exe.

mono-config.h is necessary because it needs to contain platform-specific macros. In particular, Linux needs:

Mono_Posix_ToStatvfs (struct statvfs *to, struct Mono_Posix_Statvfs *to);

while OS X and *BSD need:

Mono_Posix_ToStatvfs (struct statfs *to, struct Mono_Posix_Statvfs *to);

Note struct statvfs vs. struct statfs. The mono/posix/helper.h header needs to "paper over" the difference, and thus needs to know which type the platform prefers. helper.h thus looks like:

  struct statvfs;
  int Mono_Posix_ToStatvfs (struct statvfs *from, 
      struct Mono_Posix_Statvfs *to);
  struct statfs;
  int Mono_Posix_ToStatvfs (struct statfs *from, 
      struct Mono_Posix_Statvfs *to);

One of MONO_HAVE_STATVFS or MONO_HAVE_STATFS would be defined in mono-config.h.


There are two major changes:

The MapAttribute attribute is public so that make-map.exe can use a publically exposed API for code generation purposes which can be used by other libraries (Mono.Fuse makes use of these changes).

make-map.exe can also generate structure declarations and delegate declarations in addition to P/Invoke function declarations, allowing for a better, automated interface between C and C#.

Previously, [Map] could only be used on enumerations.

Now, [Map] can be used on classes, structures, and delegates, to create a C declaration of the C# type, suitable for P/Invoke purposes, e.g. the C# code:

[Map] struct Stat {public FilePermissions mode;}

would generate the C declaration

struct Namespace_Stat {unsigned int mode;};

The MapAttribute.NativeType property is used to specify that type conversion functions should be generated, thus:

[Map ("struct stat")] struct Stat {public FilePermissions mode;}

would generate

struct Namespace_Stat {unsigned int mode;};
int Namespace_ToStat (struct stat *from, struct Namespace_Stat *to);
int Namespace_FromStat (struct Namespace_Stat *from, struct stat *to);

along with the actual implementations of Namespace_ToStat() and Namespace_FromStat().

The MapAttribute.NativeSymbolPrefix property is used to specify the C "namespace" to use:

[Map (NativeSymbolPrefix="Foo")] struct Stat {FilePermissiond mode;}


struct Foo_Stat {unsigned int mode;};

This prefix is also used for the conversion functions.

(You may be wondering why NativeSymbolPrefix exists at all. This is for reasonable symbol versioning -- make-map.exe currently has a "hack" in place to rename Mono.Unix(.Native) to Mono_Posix, a hack I'd like to remove, and NativeSymbolPrefix allows the Mono.Unix.Native types to have a Mono_Posix C namespace in a reasonably general manner.)

The previously internal Mono.Unix.HeaderAttribute has been removed. The HeaderAttribute.Includes and HeaderAttribute.Defines properties have been replaced with make-map.exe command-line arguments. In particular, HeaderAttribute.Includes has been replaced with --autoconf-header, --impl-header, --impl-macro, --public-header, and --public-macro (the first three modify the generated .c file, while the latter two modify the generated .h file).

Finally, make-map.exe has been renamed and moved from mcs/class/Mono.Posix/Mono.Unix.Native/make-map.exe to mcs/tools/create-native-map/create-native-map.exe.


  1. Go to for the patches and source download.
  2. Apply mcs.patch to a mcs checkout, rebuild, and install.
  3. Apply mono.patch to a mono checkout, rebuild, and install.
  4. Build mono-fuse-0.1.0.tar.gz in "the standard manner" (./configure ; make ; make install).


Posted on 29 Aug 2006 | Path: /development/mono/ | Permalink
blog comments powered by Disqus