GtkSharp/glib/Marshaller.cs

159 lines
3.7 KiB
C#
Raw Normal View History

// GLibSharp.Marshaller.cs : Marshalling utils
//
// Author: Rachel Hestilow <rachel@nullenvoid.com>
//
// (c) 2002, 2003 Rachel Hestilow
namespace GLibSharp {
using System;
using System.Runtime.InteropServices;
/// <summary>
/// Marshalling utilities
/// </summary>
///
/// <remarks>
/// Utility class for internal wrapper use
/// </remarks>
public class Marshaller {
//
// Do not allow instances of this
//
private Marshaller () {}
[DllImport("libglib-2.0-0.dll")]
static extern void g_free (IntPtr mem);
public static string PtrToStringGFree (IntPtr ptr) {
string ret = Marshal.PtrToStringAnsi (ptr);
g_free (ptr);
return ret;
}
[DllImport("libglib-2.0-0.dll")]
static extern void g_strfreev (IntPtr mem);
public static string[] PtrToStringGFree (IntPtr[] ptrs) {
// The last pointer is a null terminator.
string[] ret = new string[ptrs.Length - 1];
for (int i = 0; i < ret.Length; i++) {
ret[i] = Marshal.PtrToStringAnsi (ptrs[i]);
g_free (ptrs[i]);
}
return ret;
}
[DllImport("libglib-2.0-0.dll")]
static extern IntPtr g_strdup (string str);
public static IntPtr StringToPtrGStrdup (string str) {
return g_strdup (str);
}
// Argv marshalling -- unpleasantly complex, but
// don't know of a better way to do it.
//
// Currently, the 64-bit cleanliness is
// hypothetical. It's also ugly, but I don't know of a
// construct to handle both 32 and 64 bitness
// transparently, since we need to alloc buffers of
// [native pointer size] * [count] bytes.
[DllImport("libglib-2.0-0.dll")]
static extern IntPtr g_malloc(ulong size);
static bool check_sixtyfour () {
int szint = Marshal.SizeOf (typeof (int));
int szlong = Marshal.SizeOf (typeof (long));
int szptr = IntPtr.Size;
if (szptr == szint)
return false;
if (szptr == szlong)
return true;
throw new Exception ("Pointers are neither int- nor long-sized???");
}
static IntPtr make_buf_32 (string[] args)
{
int[] ptrs = new int[args.Length];
for (int i = 0; i < args.Length; i++)
ptrs[i] = (int) Marshal.StringToHGlobalAuto (args[i]);
IntPtr buf = g_malloc ((ulong) Marshal.SizeOf(typeof(string)) *
(ulong) args.Length);
Marshal.Copy (ptrs, 0, buf, ptrs.Length);
return buf;
}
static IntPtr make_buf_64 (string[] args)
{
long[] ptrs = new long[args.Length];
for (int i = 0; i < args.Length; i++)
ptrs[i] = (long) Marshal.StringToHGlobalAuto (args[i]);
IntPtr buf = g_malloc ((ulong) Marshal.SizeOf(typeof(string)) *
(ulong) args.Length);
Marshal.Copy (ptrs, 0, buf, ptrs.Length);
return buf;
}
public static IntPtr ArgvToArrayPtr (string[] args)
{
if (args.Length == 0)
return IntPtr.Zero;
if (check_sixtyfour ())
return make_buf_64 (args);
return make_buf_32 (args);
}
// should we be freeing these pointers? they're marshalled
// from our own strings, so I think not ...
static string[] unmarshal_32 (IntPtr buf, int argc)
{
int[] ptrs = new int[argc];
string[] args = new string[argc];
Marshal.Copy (buf, ptrs, 0, argc);
for (int i = 0; i < ptrs.Length; i++)
args[i] = Marshal.PtrToStringAuto ((IntPtr) ptrs[i]);
return args;
}
static string[] unmarshal_64 (IntPtr buf, int argc)
{
long[] ptrs = new long[argc];
string[] args = new string[argc];
Marshal.Copy (buf, ptrs, 0, argc);
for (int i = 0; i < ptrs.Length; i++)
args[i] = Marshal.PtrToStringAuto ((IntPtr) ptrs[i]);
return args;
}
public static string[] ArrayPtrToArgv (IntPtr array, int argc)
{
if (argc == 0)
return new string[0];
if (check_sixtyfour ())
return unmarshal_64 (array, argc);
return unmarshal_32 (array, argc);
}
}
}