2

我有一个 C#/Mono/Gtk# 程序,它只是将放在窗口中的文件加载为 Gdk.Pixbuf 并显示它们。

它在 Ubuntu 上运行良好。但在 Windows 上,如果我尝试删除具有非 ASCII 文件名的文件,例如 C:\áéíóú.jpg,程序将崩溃。我首先认为这是我的代码有问题。所以我做了一个简单的测试用例。

Console.WriteLine("{0} exists? {1}", Filename, File.Exists(Filename));
Pixbuf pixels = new Pixbuf (Filename)

输出

C:\áéíóú.jpg 存在吗?True
GLib.GException: 无法打开文件 'C:\áéíóú.jpg': 没有这样的文件或目录

事实证明,Glib 无法找出存在的文件,存在。而且我不知道如何修复它,以便我可以从 Unicode 文件名将图像文件加载到 Windows 上的 Pixbuf 中。

4

1 回答 1

2

这似乎是 gtk-sharp<->gdk-pixbuf 互操作中的问题。

显然,在除 windows 之外的每个操作系统上,gdk_pixbuf_new_from_file都采用 utf8 编码的文件名。但是,在 Windows 上,此函数被重命名gdk_pixbuf_new_from_file_utf8并替换为一个包装器,该包装器进行区域设置转换并继续调用 utf8 版本。gtk-sharp 不知道这一点并使用gdk_pixbuf_new_from_file传递 utf8 参数,因此 Windows 上意外的额外语言环境转换会破坏文件名。

作为一种解决方法,我建议使用Pixbuf采用 aStream而不是文件名的构造函数,但张贴者报告说不能正确加载他的图像。

更新: 幸运的是,Pixbuf 包装类有一个构造函数,它接受现有 pixbuf 对象的原始 IntPtr。因此,错误构造函数中的代码可以在一些辅助方法中复制、修复和隐藏,例如:

[DllImport("libgdk_pixbuf-2.0-0.dll")]
static extern IntPtr gdk_pixbuf_new_from_file_utf8(IntPtr filename, out IntPtr error);

static Pixbuf CreatePixbufWin32(string filename)
{
    IntPtr native_filename = GLib.Marshaller.StringToPtrGStrdup(filename);
    IntPtr error = IntPtr.Zero;
    IntPtr raw = gdk_pixbuf_new_from_file_utf8(native_filename, out error);
    GLib.Marshaller.Free(native_filename);
    if (error != IntPtr.Zero) throw new GLib.GException(error);
    return new Pixbuf(raw);
}

static Pixbuf CreatePixbuf(string filename)
{
    if (Environment.OSVersion.Platform == PlatformID.Win32NT)
    {
        return CreatePixbufWin32(filename);
    }
    return new Pixbuf(filename);
}

我已经成功地测试了这一点。希望这可以帮助。

于 2012-10-18T18:38:50.913 回答