Using GhostScript 9.10 in Windows with Unicode characters in parameters

江枫思渺然 提交于 2019-12-11 04:00:52

问题


I want to use Ghostscript in a .NET / C# application to convert a .tiff file to PDF. My problem: When the file path contains non-ansi characters (e.g. Umlaute), the function

gsapi_init_with_args 

fails. (With GS 8.x, it works fine!). I found information that the behaviour was changed in 9.x, and I also found a function called

gsapi_init_with_argsW

And this function should work with .NET without any problems (see http://permalink.gmane.org/gmane.comp.printing.ghostscript.cvs/31721)

So I use the following DLLImport:

[DllImport(@"gsdll32.dll")]
public static extern int gsapi_init_with_argsW( IntPtr instace, int argc, string[] argv);

but this still does not work, I get the error:

Error: /undefinedfilename
in (C:\\304NDERUNGEN\\TEST.PDF)

The name of the file schould be

C:\\ÄNDERUNGEN\\TEST.PDF

so the umlaut "Ä" is not recognized correctly.

I´ve search the web a lot but did not found a solution.

Any idea? Thank you!


回答1:


I suspect that you will need to use UTF-8 here. Make a call to gs_set_arg_encoding passing GS_ARG_ENCODING_UTF8.

Any strings that you pass to Ghostscript should be declared as IntPtr. To convert from a C# string to a null-terminated UTF-8 encoded string use this function provided by Hans Passant:

public static IntPtr NativeUtf8FromString(string managedString) 
{
    int len = Encoding.UTF8.GetByteCount(managedString);
    byte[] buffer = new byte[len + 1]; // null-terminator allocated
    Encoding.UTF8.GetBytes(managedString, 0, managedString.Length, buffer, 0);
    IntPtr nativeUtf8 = Marshal.AllocHGlobal(buffer.Length);
    Marshal.Copy(buffer, 0, nativeUtf8, buffer.Length);
    return nativeUtf8;
}

Make sure that you remember to clean up with a call to Marshal.FreeHGlobal.

The overall code might look a little like this:

public class Ghostscript
{
    public const int GS_ARG_ENCODING_LOCAL = 0;
    public const int GS_ARG_ENCODING_UTF8 = 1;

    [DllImport("gsdll32.dll")]
    private static extern int gsapi_new_instance(out IntPtr inst, IntPtr handle);

    [DllImport("gsdll32.dll")]
    private static extern int gsapi_set_arg_encoding(IntPtr inst, int encoding);

    [DllImport("gsdll32.dll")]
    private static extern int gsapi_init_with_args(IntPtr inst, int argc, IntPtr[] argv);

    [DllImport("gsdll32.dll")]
    private static extern int gsapi_exit(IntPtr inst);

    [DllImport("gsdll32.dll")]
    private static extern void gsapi_delete_instance(IntPtr inst);

    private static void checkReturnValue(int retval)
    {
        if (retval != 0)
            throw ...; // implement error handling here
    }

    public static void run(string[] argv)
    {
        IntPtr inst;
        checkReturnValue(gsapi_new_instance(out inst, IntPtr.Zero));
        try
        {
            IntPtr[] utf8argv = new IntPtr[argv.length];
            for (int i=0; i<utf8argv.Length; i++)
                utf8argv[i] = NativeUtf8FromString(argv[i]);
            try
            {
                checkReturnValue(gsapi_set_arg_encoding(inst, GS_ARG_ENCODING_UTF8));
                checkReturnValue(gsapi_init_with_args(inst, utf8argv.Length, utf8argv));
                checkReturnValue(gsapi_exit(inst));
            finally
            {
                for (int i=0; i<utf8argv.Length; i++)
                    Marshal.FreeHGlobal(utf8argv[i]);
            }
        }
        finally
        {
            gsapi_delete_instance(inst);
        }
    }
}


来源:https://stackoverflow.com/questions/21251895/using-ghostscript-9-10-in-windows-with-unicode-characters-in-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!