list-filesystems: Use core list-filesystems API (RHBZ#642933).
[libguestfs.git] / generator / generator_csharp.ml
1 (* libguestfs
2  * Copyright (C) 2009-2010 Red Hat Inc.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  *)
18
19 (* Please read generator/README first. *)
20
21 open Printf
22
23 open Generator_types
24 open Generator_utils
25 open Generator_pr
26 open Generator_docstrings
27 open Generator_optgroups
28 open Generator_actions
29 open Generator_structs
30
31 let rec generate_csharp () =
32   generate_header CPlusPlusStyle LGPLv2plus;
33
34   (* XXX Make this configurable by the C# assembly users. *)
35   let library = "libguestfs.so.0" in
36
37   pr "\
38 // These C# bindings are highly experimental at present.
39 //
40 // Firstly they only work on Linux (ie. Mono).  In order to get them
41 // to work on Windows (ie. .Net) you would need to port the library
42 // itself to Windows first.
43 //
44 // The second issue is that some calls are known to be incorrect and
45 // can cause Mono to segfault.  Particularly: calls which pass or
46 // return string[], or return any structure value.  This is because
47 // we haven't worked out the correct way to do this from C#.  Also
48 // we don't handle functions that take optional arguments at all.
49 //
50 // The third issue is that when compiling you get a lot of warnings.
51 // We are not sure whether the warnings are important or not.
52 //
53 // Fourthly we do not routinely build or test these bindings as part
54 // of the make && make check cycle, which means that regressions might
55 // go unnoticed.
56 //
57 // Suggestions and patches are welcome.
58
59 // To compile:
60 //
61 // gmcs Libguestfs.cs
62 // mono Libguestfs.exe
63 //
64 // (You'll probably want to add a Test class / static main function
65 // otherwise this won't do anything useful).
66
67 using System;
68 using System.IO;
69 using System.Runtime.InteropServices;
70 using System.Runtime.Serialization;
71 using System.Collections;
72
73 namespace Guestfs
74 {
75   class Error : System.ApplicationException
76   {
77     public Error (string message) : base (message) {}
78     protected Error (SerializationInfo info, StreamingContext context) {}
79   }
80
81   class Guestfs
82   {
83     IntPtr _handle;
84
85     [DllImport (\"%s\")]
86     static extern IntPtr guestfs_create ();
87
88     public Guestfs ()
89     {
90       _handle = guestfs_create ();
91       if (_handle == IntPtr.Zero)
92         throw new Error (\"could not create guestfs handle\");
93     }
94
95     [DllImport (\"%s\")]
96     static extern void guestfs_close (IntPtr h);
97
98     ~Guestfs ()
99     {
100       guestfs_close (_handle);
101     }
102
103     [DllImport (\"%s\")]
104     static extern string guestfs_last_error (IntPtr h);
105
106 " library library library;
107
108   (* Generate C# structure bindings.  We prefix struct names with
109    * underscore because C# cannot have conflicting struct names and
110    * method names (eg. "class stat" and "stat").
111    *)
112   List.iter (
113     fun (typ, cols) ->
114       pr "    [StructLayout (LayoutKind.Sequential)]\n";
115       pr "    public class _%s {\n" typ;
116       List.iter (
117         function
118         | name, FChar -> pr "      char %s;\n" name
119         | name, FString -> pr "      string %s;\n" name
120         | name, FBuffer ->
121             pr "      uint %s_len;\n" name;
122             pr "      string %s;\n" name
123         | name, FUUID ->
124             pr "      [MarshalAs (UnmanagedType.ByValTStr, SizeConst=16)]\n";
125             pr "      string %s;\n" name
126         | name, FUInt32 -> pr "      uint %s;\n" name
127         | name, FInt32 -> pr "      int %s;\n" name
128         | name, (FUInt64|FBytes) -> pr "      ulong %s;\n" name
129         | name, FInt64 -> pr "      long %s;\n" name
130         | name, FOptPercent -> pr "      float %s; /* [0..100] or -1 */\n" name
131       ) cols;
132       pr "    }\n";
133       pr "\n"
134   ) structs;
135
136   (* Generate C# function bindings. *)
137   List.iter (
138     fun (name, (ret, args, optargs), _, _, _, shortdesc, _) ->
139       let rec csharp_return_type () =
140         match ret with
141         | RErr -> "void"
142         | RBool n -> "bool"
143         | RInt n -> "int"
144         | RInt64 n -> "long"
145         | RConstString n
146         | RConstOptString n
147         | RString n
148         | RBufferOut n -> "string"
149         | RStruct (_,n) -> "_" ^ n
150         | RHashtable n -> "Hashtable"
151         | RStringList n -> "string[]"
152         | RStructList (_,n) -> sprintf "_%s[]" n
153
154       and c_return_type () =
155         match ret with
156         | RErr
157         | RBool _
158         | RInt _ -> "int"
159         | RInt64 _ -> "long"
160         | RConstString _
161         | RConstOptString _
162         | RString _
163         | RBufferOut _ -> "string"
164         | RStruct (_,n) -> "_" ^ n
165         | RHashtable _
166         | RStringList _ -> "string[]"
167         | RStructList (_,n) -> sprintf "_%s[]" n
168
169       and c_error_comparison () =
170         match ret with
171         | RErr
172         | RBool _
173         | RInt _
174         | RInt64 _ -> "== -1"
175         | RConstString _
176         | RConstOptString _
177         | RString _
178         | RBufferOut _
179         | RStruct (_,_)
180         | RHashtable _
181         | RStringList _
182         | RStructList (_,_) -> "== null"
183
184       and generate_extern_prototype () =
185         pr "    static extern %s guestfs_%s (IntPtr h"
186           (c_return_type ()) name;
187         List.iter (
188           function
189           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
190           | FileIn n | FileOut n
191           | Key n
192           | BufferIn n ->
193               pr ", [In] string %s" n
194           | StringList n | DeviceList n ->
195               pr ", [In] string[] %s" n
196           | Bool n ->
197               pr ", bool %s" n
198           | Int n ->
199               pr ", int %s" n
200           | Int64 n ->
201               pr ", long %s" n
202         ) args;
203         pr ");\n"
204
205       and generate_public_prototype () =
206         pr "    public %s %s (" (csharp_return_type ()) name;
207         let comma = ref false in
208         let next () =
209           if !comma then pr ", ";
210           comma := true
211         in
212         List.iter (
213           function
214           | Pathname n | Device n | Dev_or_Path n | String n | OptString n
215           | FileIn n | FileOut n
216           | Key n
217           | BufferIn n ->
218               next (); pr "string %s" n
219           | StringList n | DeviceList n ->
220               next (); pr "string[] %s" n
221           | Bool n ->
222               next (); pr "bool %s" n
223           | Int n ->
224               next (); pr "int %s" n
225           | Int64 n ->
226               next (); pr "long %s" n
227         ) args;
228         pr ")\n"
229
230       and generate_call () =
231         pr "guestfs_%s (_handle" name;
232         List.iter (fun arg -> pr ", %s" (name_of_argt arg)) args;
233         pr ");\n";
234       in
235
236       pr "    [DllImport (\"%s\")]\n" library;
237       generate_extern_prototype ();
238       pr "\n";
239       pr "    /// <summary>\n";
240       pr "    /// %s\n" shortdesc;
241       pr "    /// </summary>\n";
242       generate_public_prototype ();
243       pr "    {\n";
244       pr "      %s r;\n" (c_return_type ());
245       pr "      r = ";
246       generate_call ();
247       pr "      if (r %s)\n" (c_error_comparison ());
248       pr "        throw new Error (guestfs_last_error (_handle));\n";
249       (match ret with
250        | RErr -> ()
251        | RBool _ ->
252            pr "      return r != 0 ? true : false;\n"
253        | RHashtable _ ->
254            pr "      Hashtable rr = new Hashtable ();\n";
255            pr "      for (size_t i = 0; i < r.Length; i += 2)\n";
256            pr "        rr.Add (r[i], r[i+1]);\n";
257            pr "      return rr;\n"
258        | RInt _ | RInt64 _ | RConstString _ | RConstOptString _
259        | RString _ | RBufferOut _ | RStruct _ | RStringList _
260        | RStructList _ ->
261            pr "      return r;\n"
262       );
263       pr "    }\n";
264       pr "\n";
265   ) all_functions_sorted;
266
267   pr "  }
268 }
269 "