[Mono-list] PInvoke:TNG

Fergus Henderson fjh@cs.mu.oz.au
Fri, 27 Jul 2001 16:57:57 +1000


--IJpNTDwzlM2Ie8A6
Content-Type: text/plain; charset=us-ascii

I wrote:

> The other approach is to write wrappers in C.
> Then you don't need any #ifdefs.

To make that a little more concrete, here's how you could wrap stat().
First, you write a little wrapper in C, that use types with known
sizes and layouts:

	struct my_stat {
		int64_t uid;
		int64_t gid;
		/* etc. */
	}

	int64_t my_stat (const char *filename, struct my_stat *mystat)
	{
		struct stat s;
		int result;

		result = stat(filename, &s);

		mystat->uid = s->st_uid;
		mystat->gid = s->st_gid;
		/* etc. */

		return result;
	}

You then compile this file to say `libwrappers.so'.

In the C# code, you can defining a matching interface,
and you can import the C wrapper in a straight-forward manner:

	struct my_stat {
		long uid;
		long gid;
		// etc.
	}

	[DllImport("libwrappers")]
	public static long stat(byte *filename, my_stat *ms)

-- 
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
The University of Melbourne         |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.

--IJpNTDwzlM2Ie8A6
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="posix.stat.m"

%------------------------------------------------------------------------------%
% Copyright (C) 2001 The University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB in the Mercury distribution.
%------------------------------------------------------------------------------%
%
% module: posix__stat.m
% main author: Michael Day <miked@lendtech.com.au>
%
%------------------------------------------------------------------------------%
:- module posix__stat.

:- interface.

:- import_module int, string, time.

:- type file_type
    --->    file
    ;	    directory
    ;	    symbolic_link
    ;	    character_device
    ;	    block_device
    ;	    fifo
    ;	    unknown
    .

:- type stat.

:- func dev(stat) = dev_t.
:- func ino(stat) = ino_t.
:- func mode(stat) = mode_t.
:- func file_type(stat) = file_type.
:- func nlink(stat) = int.
:- func uid(stat) = uid_t.
:- func gid(stat) = gid_t.
:- func rdev(stat) = dev_t.
:- func size(stat) = int.
:- func blksize(stat) = int.
:- func blocks(stat) = int.
:- func atime(stat) = time_t.
:- func mtime(stat) = time_t.
:- func ctime(stat) = time_t.

:- pred stat(string, posix__result(stat), io__state, io__state).
:- mode stat(in, out, di, uo) is det.

%------------------------------------------------------------------------------%

:- implementation.

:- pragma c_header_code("
	#include <sys/types.h>
	#include <sys/stat.h>
	#include <unistd.h>
").

%------------------------------------------------------------------------------%

:- type stat ---> stat(c_pointer).

stat(Path, Result) -->
	stat0(Path, Res, Stat),
	( if { Res = 0 } then
		{ Result = ok(Stat) }
	else
		errno(Err),
		{ Result = error(Err) }
	).				    

:- pred stat0(string, int, stat, io__state, io__state).
:- mode stat0(in, out, out, di, uo) is det.

:- pragma c_code(stat0(Path::in, Res::out, Stat::out, IO0::di, IO::uo),
		[will_not_call_mercury, thread_safe], "{
	Stat = (MR_Word) MR_GC_NEW(struct stat);
	Res = stat(Path, (struct stat *)Stat);
	IO = IO0;
}").

file_type(Stat) =
	( if is_slnk(Mode) then symbolic_link
	else if is_reg(Mode) then file
	else if is_dir(Mode) then directory
	else if is_chr(Mode) then character_device
	else if is_blk(Mode) then block_device
	else if is_fifo(Mode) then fifo
	else unknown ) :- Mode = Stat ^ (mode).

:- pred is_slnk(mode_t).
:- mode is_slnk(in) is semidet.

:- pragma c_code(is_slnk(Mode::in), [will_not_call_mercury, thread_safe], "
	SUCCESS_INDICATOR = S_ISLNK(Mode); ").

:- pred is_reg(mode_t).
:- mode is_reg(in) is semidet.

:- pragma c_code(is_reg(Mode::in), [will_not_call_mercury, thread_safe], "
	SUCCESS_INDICATOR = S_ISREG(Mode); ").

:- pred is_dir(mode_t).
:- mode is_dir(in) is semidet.

:- pragma c_code(is_dir(Mode::in), [will_not_call_mercury, thread_safe], "
	SUCCESS_INDICATOR = S_ISDIR(Mode); ").

:- pred is_chr(mode_t).
:- mode is_chr(in) is semidet.

:- pragma c_code(is_chr(Mode::in), [will_not_call_mercury, thread_safe], "
	SUCCESS_INDICATOR = S_ISCHR(Mode); ").

:- pred is_blk(mode_t).
:- mode is_blk(in) is semidet.

:- pragma c_code(is_blk(Mode::in), [will_not_call_mercury, thread_safe], "
	SUCCESS_INDICATOR = S_ISBLK(Mode); ").

:- pred is_fifo(mode_t).
:- mode is_fifo(in) is semidet.

:- pragma c_code(is_fifo(Mode::in), [will_not_call_mercury, thread_safe], "
	SUCCESS_INDICATOR = S_ISFIFO(Mode); ").

:- pragma c_code(dev(S::in) = (Dev::out),
	[will_not_call_mercury, thread_safe],
	"Dev = ((struct stat *)S)->st_dev; ").

:- pragma c_code(ino(S::in) = (Ino::out),
	[will_not_call_mercury, thread_safe],
	"Ino = ((struct stat *)S)->st_ino; ").

:- pragma c_code(mode(S::in) = (Mode::out),
	[will_not_call_mercury, thread_safe],
	"Mode = ((struct stat *)S)->st_mode; ").

:- pragma c_code(nlink(S::in) = (Nlink::out),
	[will_not_call_mercury, thread_safe],
	"Nlink = ((struct stat *)S)->st_nlink; ").

:- pragma c_code(uid(S::in) = (Uid::out),
	[will_not_call_mercury, thread_safe],
	"Uid = ((struct stat *)S)->st_uid; ").

:- pragma c_code(gid(S::in) = (Gid::out),
	[will_not_call_mercury, thread_safe],
	"Gid = ((struct stat *)S)->st_gid; ").

:- pragma c_code(rdev(S::in) = (Rdev::out),
	[will_not_call_mercury, thread_safe],
	"Rdev = ((struct stat *)S)->st_rdev; ").

:- pragma c_code(size(S::in) = (Size::out),
	[will_not_call_mercury, thread_safe],
	"Size = ((struct stat *)S)->st_size; ").

:- pragma c_code(blksize(S::in) = (Blksize::out),
	[will_not_call_mercury, thread_safe],
	"Blksize = ((struct stat *)S)->st_blksize; ").

:- pragma c_code(blocks(S::in) = (Blocks::out),
	[will_not_call_mercury, thread_safe],
	"Blocks = ((struct stat *)S)->st_blocks; ").

:- pragma c_code(atime(S::in) = (Atime::out),
	[will_not_call_mercury, thread_safe],
	"Atime = ((struct stat *)S)->st_atime; ").

:- pragma c_code(mtime(S::in) = (Mtime::out),
	[will_not_call_mercury, thread_safe],
	"Mtime = ((struct stat*)S)->st_mtime; ").

:- pragma c_code(ctime(S::in) = (Ctime::out),
	[will_not_call_mercury, thread_safe],
	"Ctime = ((struct stat *)S)->st_ctime; ").

%------------------------------------------------------------------------------%


--IJpNTDwzlM2Ie8A6--