Experimental C# bindings.

Tested in only limited situations, with Mono on Linux.
This commit is contained in:
Richard Jones
2010-01-02 19:46:20 +00:00
committed by Richard Jones
parent d3c615c2d6
commit c0e4b5dc69
4 changed files with 224 additions and 7 deletions

View File

@@ -74,6 +74,9 @@ capitests/
contrib/
Outside contributions, experimental parts.
csharp/
Experimental C# bindings.
daemon/
The daemon that runs inside the guest and carries out actions.

5
README
View File

@@ -16,8 +16,9 @@ LVs, what filesystem is in each LV, etc.). It can also run commands
in the context of the guest. Also you can access filesystems over FTP.
Libguestfs is a library that can be linked with C and C++ management
programs (or management programs written in OCaml, Perl, Python, Ruby, Java
or Haskell). You can also use it from shell scripts or the command line.
programs (or management programs written in OCaml, Perl, Python, Ruby,
Java, Haskell or C#). You can also use it from shell scripts or the
command line.
Libguestfs was written by Richard W.M. Jones (rjones@redhat.com) and
hacked on by lots of other people. For discussion, development,

View File

@@ -52,6 +52,7 @@ stamp-generator: generator.ml
mkdir -p $(top_srcdir)/perl/lib/Sys
mkdir -p $(top_srcdir)/ruby/ext/guestfs
mkdir -p $(top_srcdir)/java/com/redhat/et/libguestfs
mkdir -p $(top_srcdir)/csharp
cd $(top_srcdir) && ocaml -warn-error A src/generator.ml
include_HEADERS = guestfs.h guestfs-actions.h guestfs-structs.h

View File

@@ -4815,16 +4815,18 @@ let copyright_years =
if this_year > 2009 then sprintf "2009-%04d" this_year else "2009"
(* Generate a header block in a number of standard styles. *)
type comment_style = CStyle | HashStyle | OCamlStyle | HaskellStyle
type comment_style =
CStyle | CPlusPlusStyle | HashStyle | OCamlStyle | HaskellStyle
type license = GPLv2plus | LGPLv2plus
let generate_header ?(extra_inputs = []) comment license =
let inputs = "src/generator.ml" :: extra_inputs in
let c = match comment with
| CStyle -> pr "/* "; " *"
| HashStyle -> pr "# "; "#"
| OCamlStyle -> pr "(* "; " *"
| HaskellStyle -> pr "{- "; " " in
| CStyle -> pr "/* "; " *"
| CPlusPlusStyle -> pr "// "; "//"
| HashStyle -> pr "# "; "#"
| OCamlStyle -> pr "(* "; " *"
| HaskellStyle -> pr "{- "; " " in
pr "libguestfs generated file\n";
pr "%s WARNING: THIS FILE IS GENERATED FROM:\n" c;
List.iter (pr "%s %s\n" c) inputs;
@@ -4865,6 +4867,7 @@ let generate_header ?(extra_inputs = []) comment license =
);
(match comment with
| CStyle -> pr " */\n"
| CPlusPlusStyle
| HashStyle -> ()
| OCamlStyle -> pr " *)\n"
| HaskellStyle -> pr "-}\n"
@@ -9918,6 +9921,214 @@ and generate_haskell_prototype ~handle ?(hs = false) style =
);
pr ")"
and generate_csharp () =
generate_header CPlusPlusStyle LGPLv2plus;
(* XXX Make this configurable by the C# assembly users. *)
let library = "libguestfs.so.0" in
pr "\
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Collections;
namespace Guestfs
{
class Error : System.ApplicationException
{
public Error (string message) : base (message) {}
protected Error (SerializationInfo info, StreamingContext context) {}
}
class Guestfs
{
IntPtr _handle;
[DllImport (\"%s\")]
static extern IntPtr guestfs_create ();
public Guestfs ()
{
_handle = guestfs_create ();
if (_handle == IntPtr.Zero)
throw new Error (\"could not create guestfs handle\");
}
[DllImport (\"%s\")]
static extern void guestfs_close (IntPtr h);
~Guestfs ()
{
guestfs_close (_handle);
}
[DllImport (\"%s\")]
static extern string guestfs_last_error (IntPtr h);
" library library library;
(* Generate C# structure bindings. We prefix struct names with
* underscore because C# cannot have conflicting struct names and
* method names (eg. "class stat" and "stat").
*)
List.iter (
fun (typ, cols) ->
pr " [StructLayout (LayoutKind.Sequential)]\n";
pr " public class _%s {\n" typ;
List.iter (
function
| name, FChar -> pr " char %s;\n" name
| name, FString -> pr " string %s;\n" name
| name, FBuffer ->
pr " uint %s_len;\n" name;
pr " string %s;\n" name
| name, FUUID ->
pr " [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
pr " string %s;\n" name
| name, FUInt32 -> pr " uint %s;\n" name
| name, FInt32 -> pr " int %s;\n" name
| name, (FUInt64|FBytes) -> pr " ulong %s;\n" name
| name, FInt64 -> pr " long %s;\n" name
| name, FOptPercent -> pr " float %s; /* [0..100] or -1 */\n" name
) cols;
pr " }\n";
pr "\n"
) structs;
(* Generate C# function bindings. *)
List.iter (
fun (name, style, _, _, _, shortdesc, _) ->
let rec csharp_return_type () =
match fst style with
| RErr -> "void"
| RBool n -> "bool"
| RInt n -> "int"
| RInt64 n -> "long"
| RConstString n
| RConstOptString n
| RString n
| RBufferOut n -> "string"
| RStruct (_,n) -> "_" ^ n
| RHashtable n -> "Hashtable"
| RStringList n -> "string[]"
| RStructList (_,n) -> sprintf "_%s[]" n
and c_return_type () =
match fst style with
| RErr
| RBool _
| RInt _ -> "int"
| RInt64 _ -> "long"
| RConstString _
| RConstOptString _
| RString _
| RBufferOut _ -> "string"
| RStruct (_,n) -> "_" ^ n
| RHashtable _
| RStringList _ -> "string[]"
| RStructList (_,n) -> sprintf "_%s[]" n
and c_error_comparison () =
match fst style with
| RErr
| RBool _
| RInt _
| RInt64 _ -> "== -1"
| RConstString _
| RConstOptString _
| RString _
| RBufferOut _
| RStruct (_,_)
| RHashtable _
| RStringList _
| RStructList (_,_) -> "== null"
and generate_extern_prototype () =
pr " static extern %s guestfs_%s (IntPtr h"
(c_return_type ()) name;
List.iter (
function
| Pathname n | Device n | Dev_or_Path n | String n | OptString n
| FileIn n | FileOut n ->
pr ", [In] string %s" n
| StringList n | DeviceList n ->
pr ", [In] string[] %s" n
| Bool n ->
pr ", bool %s" n
| Int n ->
pr ", int %s" n
| Int64 n ->
pr ", long %s" n
) (snd style);
pr ");\n"
and generate_public_prototype () =
pr " public %s %s (" (csharp_return_type ()) name;
let comma = ref false in
let next () =
if !comma then pr ", ";
comma := true
in
List.iter (
function
| Pathname n | Device n | Dev_or_Path n | String n | OptString n
| FileIn n | FileOut n ->
next (); pr "string %s" n
| StringList n | DeviceList n ->
next (); pr "string[] %s" n
| Bool n ->
next (); pr "bool %s" n
| Int n ->
next (); pr "int %s" n
| Int64 n ->
next (); pr "long %s" n
) (snd style);
pr ")\n"
and generate_call () =
pr "guestfs_%s (_handle" name;
List.iter (fun arg -> pr ", %s" (name_of_argt arg)) (snd style);
pr ");\n";
in
pr " [DllImport (\"%s\")]\n" library;
generate_extern_prototype ();
pr "\n";
pr " /// <summary>\n";
pr " /// %s\n" shortdesc;
pr " /// </summary>\n";
generate_public_prototype ();
pr " {\n";
pr " %s r;\n" (c_return_type ());
pr " r = ";
generate_call ();
pr " if (r %s)\n" (c_error_comparison ());
pr " throw new Error (\"%s: \" + guestfs_last_error (_handle));\n"
name;
(match fst style with
| RErr -> ()
| RBool _ ->
pr " return r != 0 ? true : false;\n"
| RHashtable _ ->
pr " Hashtable rr = new Hashtable ();\n";
pr " for (int i = 0; i < r.Length; i += 2)\n";
pr " rr.Add (r[i], r[i+1]);\n";
pr " return rr;\n"
| RInt _ | RInt64 _ | RConstString _ | RConstOptString _
| RString _ | RBufferOut _ | RStruct _ | RStringList _
| RStructList _ ->
pr " return r;\n"
);
pr " }\n";
pr "\n";
) all_functions_sorted;
pr " }
}
"
and generate_bindtests () =
generate_header CStyle LGPLv2plus;
@@ -10924,6 +11135,7 @@ Run it from the top source directory using the command
output_to "java/Bindtests.java" generate_java_bindtests;
output_to "haskell/Guestfs.hs" generate_haskell_hs;
output_to "haskell/Bindtests.hs" generate_haskell_bindtests;
output_to "csharp/Libguestfs.cs" generate_csharp;
output_to "src/MAX_PROC_NR" generate_max_proc_nr;
(* Always generate this file last, and unconditionally. It's used