[Mono-devel-list] Mono.Posix-OEE 0.1

Jonathan Pryor jonpryor at vt.edu
Wed Sep 29 22:43:02 EDT 2004

As hinted at last Thursday, here's my current Mono.Posix restructuring
effort -- Mono.Posix Over Engineered Edition (further proof that I
over-engineer everything I touch...).

	- It's currently a stand-alone re-implementation.  As such, 
	  there is no support for the Syscall class.  This will be
	  done when I get off my duff and write a patch against CVS,
	  and not a stand-alone version.  Expect that after I fully
	  wrap all of CVS's exports and find good solutions to my
	  current list of questions (see the end).

	- It doesn't currently provide all the functionality of the
	  previous Mono.Posix, such as poll, waitpid, WIFEXITED, etc.

What is it?

It's an ABI-stable POSIX wrapper, which means that this Mono.Posix.dll
can be used on both 32-bit and 64-bit platforms.  It achieves this by
having a much larger libMonoPosixHelper.so library.

In short, any function which contains a non-pointer parameter whose size
is platform dependent is wrapped.  Which means anything containing
size_t, ssize_t, and off_t, among other types.  This constitutes a large
number of functions.

About the package

It has a makefile.  Unpack the archive, and build:

	$ tar xzf Mono-Posix-jp-0.1.tar.gz
	$ cd Mono.Posix-jp-0.1
	$ make

This will create a lot of .cs file, Mono.Posix.dll,
libMonoPosixHelper.so, and Main.exe.

Main.exe is a badly cobbled test program, which calls stat(2) on all
command line arguments, printing out their information, and tries to
write "hello\n" to the file hello.txt using a PosixStream.

The write will likely fail, as the open(2) call doesn't specify O_CREAT,
so you need to touch(1) hello.txt in advance for the write to work.

I wrote this on Fedora Core 2, so if it doesn't compile on your system,
please let me know so I know what portability issues to fix.

About the Implementation

The logic used is that "long" is assumed to change size between
platforms (32-bit or 64-bit), but "int" will always be 32-bits.  
Hopefully this is a sane assumption.

As mentioned in my last email, functions are placed in classes named
after the header file they appear in.  So open(2) is in the Fcntl class.

Furthermore, C typedefs get their own types.  This feature is debatable,
and can be changed, but I thought it was cool.  Consequently, the C:

	typedef unsigned long size_t;

Becomes the C#:

	public struct size_t : IComparable, IFormattable...
		private ulong value;
		// ...

This can get rather tedious, so I have a Perl script which generates the
structure declarations, stub-vt.pl.  (This could also be a shell script,
or any other language, if that would be preferred.  I'm not sure what
the Mono policy regarding code generation is; I haven't heard of such a
policy, anyway.)

The "typedef" classes all support implicit conversions to their
underlying type, but require explicit conversions back.  Usage is thus:

	size_t a = (size_t) (1 + 2);
	size_t b = (size_t) (a + 42);
	// ...

I also have enough POSIX support in place to fully implement my
PosixStream class.

Enumerations now get two conversion functions instead of one from
make-map.cs: a ToManagedType, and a FromManagedType.  This allows
managed code to get unmanaged values and convert them to the proper
managed equivalent (useful for Error values, as we get the unconverted
value from Marshal.GetLastWin32Error()), as well as the previous code to
convert managed values to their unmanaged equivalent.

All API exports also follow a consistent naming convention

Open Questions (more to follow, I'm sure):

What's a good class to use for the conversion helper functions
(FromManagedType() and ToManagedType())?  I'm currently using Utils, but
that's likely a common name.  I'd prefer a name that's less likely to
clash with existing classes.

What's a good alternative name to use when wrapping <string.h>?  My
current naming convention would use a String class, but this is
obviously a bad choice, so currently I'm using String_h.  Any better
suggestions?  Should I modify the other classes to have a "_h" suffix
(for ".h")?  (Thus creating classes Fcntl_h, Unistd_h, Stdio_h, etc.)

What's the best way to directly set `errno'?  Some functions don't have
a return value to check, and recommend you set errno = 0, call the
function, and then check errno for errors (see encrypt(3)).

I need some 64-bit OS advice.  Is it safe to assume (as I currently do)
that a 64-bit OS will provide the -64 API call?  I don't believe this is
actually safe, as open(2) and open64() should do the same thing on
64-bit platforms, so there isn't any need for open64() (except for

What about portable limits information?  Currently, I'm using a macro to
check if an argument is out-of-range for the current platform (to
prevent 64-bit values from being used in 32-bit APIs).  For example:

	#define mph_return_if_size_t_overflow(var) G_STMT_START{ \
		if (var > SIZE_MAX) { \
			errno = EOVERFLOW; \
			return -1; \

The problem is that SIZE_MAX is defined in <stdint.h>, as part of C99. 
Consequently this isn't portable to C89-only systems.

I also have no idea which platforms support C99 (assuming that most

An alternative approach would be to check SIZEOF_VOID_P, and use the
appropriate GLib MIN/MAX value macros to perform the checking.

I'll likely have to do this anyway, as not all typedefs get MIN/MAX
macros (such as off_t), which can make the overflow checking difficult.

 - Jon

-------------- next part --------------
A non-text attachment was scrubbed...
Name: Mono-Posix-jp-0.1.tar.gz
Type: application/x-compressed-tar
Size: 21189 bytes
Desc: not available
Url : http://lists.ximian.com/pipermail/mono-devel-list/attachments/20040929/6f8112e6/attachment.bin 

More information about the Mono-devel-list mailing list