Bug 694545 - gsapi_init_with_args when -sDevice=display on 64 bit ghostscript library
Summary: gsapi_init_with_args when -sDevice=display on 64 bit ghostscript library
Status: RESOLVED INVALID
Alias: None
Product: Ghostscript
Classification: Unclassified
Component: Client API (show other bugs)
Version: 9.10
Hardware: PC Windows 7
: P4 normal
Assignee: Default assignee
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-08-29 03:04 UTC by Josip Habjan
Modified: 2013-09-19 21:16 UTC (History)
1 user (show)

See Also:
Customer:
Word Size: ---


Attachments
Test source code (53.10 KB, application/octet-stream)
2013-08-29 04:23 UTC, Josip Habjan
Details
Simple display device test code (9.87 KB, text/x-csrc)
2013-08-30 03:11 UTC, Chris Liddell (chrisl)
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Josip Habjan 2013-08-29 03:04:24 UTC
I'm writing open source C# Ghostscript wrapper. You can try it and take a look at (http://ghostscriptnet.codeplex.com). Most of the functionality is implemented and it works on both versions (x86/x64). The problem i'm having is when i'm initializing a display device to render pdf directly to the screen (i successfully implemented gsapi_set_display_callback callback).

Arguments that i'm using are following:

string[] args = new string[] {
    "",
    "-sDEVICE=display",
    "-dTextAlphaBits=4",
    "-dGraphicAlphaBits=4",
    "-dDisplayHandle=1234",
    "-dDisplayResolution=72",
    "-dDisplayFormat=" + ((int)DISPLAY_FORMAT_COLOR.DISPLAY_COLORS_RGB | 
                            (int)DISPLAY_FORMAT_ALPHA.DISPLAY_ALPHA_NONE | 
                            (int)DISPLAY_FORMAT_DEPTH.DISPLAY_DEPTH_8 | 
                            (int)DISPLAY_FORMAT_ENDIAN.DISPLAY_LITTLEENDIAN | 
                            (int)DISPLAY_FORMAT_FIRSTROW.DISPLAY_BOTTOMFIRST).ToString() };
This arguments works well on 32 bit version and i'm able to render pdf page to the screen. Initialization works fine.

When i switch to the 64 bit version i get typecheck (e_typecheck = -20) error.

I know that 64 bit version uses -sDisplayFormat and i tried that also but with no luck.

Anyone has any idea how to initialize device as display on 64 bit version Ghostscript library? I dont think i'm missing something. Is this a bug in 64 bit version of the ghostscript library?

I tried earlier versions of Ghostscript library and i get a same error on 64 bit version.

Current version that i use is 9.09. Class where you can take a look at the code: https://ghostscriptnet.codeplex.com/SourceControl/latest#Ghostscript.NET/Ghostscript.NET/Viewer/GhostscriptViewer.cs
Comment 1 Ken Sharp 2013-08-29 03:22:32 UTC
I'm not a C# programmer. I'm prepared to look at the problem, and I can at least run a C# app under the debugger. However, I only have the express version of VS 2012 and when I try to load your application it gives me a number of warnings and errors, and then crashes Visual Studio.

I doubt that I need the full complexity of your application to investigate this. Can you please instead supply a minimal application to demonstrate the problem.

FWIW our own 64-bit executable uses the gsapi_init_with_args routine, so it *does* work under 64-bit Windows.
Comment 2 Chris Liddell (chrisl) 2013-08-29 03:57:04 UTC
On 64 bit systems the "DisplayHandle" parameter is a string, because these params are integers which are (mostly) 32 bit.

You'll need to convert the pointer value into a string, and pass it with "-sDisplayHandle=<string>"

See:
http://git.ghostscript.com/?p=ghostpdl.git;a=blob;f=gs/devices/gdevdsp.c

and search for "DisplayHandle as a string"
Comment 3 Ken Sharp 2013-08-29 04:02:28 UTC
Its also even documented in API.htm:

"     -sDisplayHandle=1234 

Where "1234" is a string. The API was changed to use a string rather than an integer/long value when support for 64 bit systems arrived. A display "handle" is often a pointer, and since these command line options have to survive being processed by Postscript machinery, and Postscript only permits 32 bit number values, a different representation was required."

Thanks Chris
Comment 4 Josip Habjan 2013-08-29 04:23:49 UTC
Created attachment 10154 [details]
Test source code

Minimal source code for test.
Comment 5 Josip Habjan 2013-08-29 04:25:33 UTC
Thank you, i will check, try what you suggested me and let you know.
Comment 6 Josip Habjan 2013-08-29 05:10:41 UTC
This are my 32 bit arguments:

string[] args_x86 = new string[] {
            "",
            "-sDEVICE=display",
            "-dTextAlphaBits=4",
            "-dGraphicAlphaBits=4",
            "-dDisplayHandle=0",
            "-dDisplayResolution=72",
            "-dDisplayFormat=" + ((int)DISPLAY_FORMAT_COLOR.DISPLAY_COLORS_RGB | 
                                    (int)DISPLAY_FORMAT_ALPHA.DISPLAY_ALPHA_NONE | 
                                    (int)DISPLAY_FORMAT_DEPTH.DISPLAY_DEPTH_8 | 
                                    (int)DISPLAY_FORMAT_ENDIAN.DISPLAY_LITTLEENDIAN | 
                                    (int)DISPLAY_FORMAT_FIRSTROW.DISPLAY_BOTTOMFIRST).ToString() };

And this are 64 bit:

string[] args_x64 = new string[] {
            "",
            "-sDEVICE=display",
            "-dTextAlphaBits=4",
            "-dGraphicAlphaBits=4",
            "-sDisplayHandle=0",
            "-dDisplayResolution=72",
            "-sDisplayFormat=" + ((int)DISPLAY_FORMAT_COLOR.DISPLAY_COLORS_RGB | 
                                    (int)DISPLAY_FORMAT_ALPHA.DISPLAY_ALPHA_NONE | 
                                    (int)DISPLAY_FORMAT_DEPTH.DISPLAY_DEPTH_8 | 
                                    (int)DISPLAY_FORMAT_ENDIAN.DISPLAY_LITTLEENDIAN | 
                                    (int)DISPLAY_FORMAT_FIRSTROW.DISPLAY_BOTTOMFIRST).ToString() };

32 bit works file, 64 returns: Unrecoverable error: typecheck in .putdeviceprops

I want display handle to be 0.
Comment 7 Chris Liddell (chrisl) 2013-08-29 05:15:22 UTC
(In reply to comment #6)
> This are my 32 bit arguments:
> 
> string[] args_x86 = new string[] {
>             "",
>             "-sDEVICE=display",
>             "-dTextAlphaBits=4",
>             "-dGraphicAlphaBits=4",
>             "-dDisplayHandle=0",
>             "-dDisplayResolution=72",
>             "-dDisplayFormat=" +
> ((int)DISPLAY_FORMAT_COLOR.DISPLAY_COLORS_RGB | 
>                                    
> (int)DISPLAY_FORMAT_ALPHA.DISPLAY_ALPHA_NONE | 
>                                    
> (int)DISPLAY_FORMAT_DEPTH.DISPLAY_DEPTH_8 | 
>                                    
> (int)DISPLAY_FORMAT_ENDIAN.DISPLAY_LITTLEENDIAN | 
>                                    
> (int)DISPLAY_FORMAT_FIRSTROW.DISPLAY_BOTTOMFIRST).ToString() };
> 
> And this are 64 bit:
> 
> string[] args_x64 = new string[] {
>             "",
>             "-sDEVICE=display",
>             "-dTextAlphaBits=4",
>             "-dGraphicAlphaBits=4",
>             "-sDisplayHandle=0",
>             "-dDisplayResolution=72",
>             "-sDisplayFormat=" +
> ((int)DISPLAY_FORMAT_COLOR.DISPLAY_COLORS_RGB | 
>                                    
> (int)DISPLAY_FORMAT_ALPHA.DISPLAY_ALPHA_NONE | 
>                                    
> (int)DISPLAY_FORMAT_DEPTH.DISPLAY_DEPTH_8 | 
>                                    
> (int)DISPLAY_FORMAT_ENDIAN.DISPLAY_LITTLEENDIAN | 
>                                    
> (int)DISPLAY_FORMAT_FIRSTROW.DISPLAY_BOTTOMFIRST).ToString() };
> 
> 32 bit works file, 64 returns: Unrecoverable error: typecheck in
> .putdeviceprops
> 
> I want display handle to be 0.

Well, 0 is still an integer, not a string.....

I *think* you'll need a string containing '0'.
Comment 8 Josip Habjan 2013-08-29 05:35:29 UTC
I solved the "string" "number" problem.
for 64 bit i'm now using -dDisplayFormat and -dDisplayHandle as suggested in API docs. 

The error i now get is: -15

**** Unable to open the display device, quitting.

Chris, the 0 in this case is a string.

For instance:
"-sDEVICE=display" - value is string
"-sDisplayHandle=0" - value is string
"-dDisplayHandle=0" - value is integer
Comment 9 Chris Liddell (chrisl) 2013-08-29 05:38:50 UTC
Well, you can get the Ghostscript source, and you can see where the parameter is being read, so you can debug why it's throwing an error.

*Or* you could create a very minimal C app which shows the error, so we can debug it.
Comment 10 Josip Habjan 2013-08-29 05:41:25 UTC
If it will be easier for you to see my screen, click on this: https://join.me/580-140-202

(it's web broser based screen sharing)
Comment 11 Josip Habjan 2013-08-30 02:09:40 UTC
I'm not C/C++ developer, can any of you please try if this works on 64 bit version?

    char **nargv;
    char arg1[64];
    char arg2[64];
    char arg3[64];
    code = gsapi_new_instance(&minst, NULL);
    gsapi_set_stdio(minst, gsdll_stdin, gsdll_stdout, gsdll_stderr);
    code = gsapi_set_display_callback(minst, &display_callback);
    sprintf(arg1, "-sDEVICE=display");
    sprintf(arg2, "-sDisplayHandle=%d", 0);
    sprintf(arg3, "-dDisplayFormat=%d", 
        DISPLAY_COLORS_RGB | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 | 
        DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST);
    nargv = (char **)malloc((argc + 4) * sizeof(char *));
    nargv[0] = argv[0];
    nargv[1] = arg1;
    nargv[2] = arg2;
    nargv[3] = arg3;
    memcpy(nargv + 4, argv + 1, argc * sizeof(char *));
    argc += 3;
    code = gsapi_init_with_args(minst, argc, nargv);

Thanks,
Josip
Comment 12 Ken Sharp 2013-08-30 03:11:05 UTC
(In reply to comment #11)
> I'm not C/C++ developer, can any of you please try if this works on 64 bit
> version?

That doesn't work on either 32 or 64-bits. This works on both:

    sprintf(arg1, "-sDEVICE=display");
    sprintf(arg2, "-sDisplayHandle=%d", 0);
    sprintf(arg3, "-dDisplayFormat=%d", 
        DISPLAY_COLORS_RGB | DISPLAY_ALPHA_NONE | DISPLAY_DEPTH_8 | 
        DISPLAY_LITTLEENDIAN | DISPLAY_BOTTOMFIRST);

    nargc = argc + 3;
    nargv = (char **)malloc((nargc + 1) * sizeof(char *));
    nargv[0] = argv[0];
    nargv[1] = arg1;
    nargv[2] = arg2;
    nargv[3] = arg3;
    memcpy(&nargv[4], &argv[1], argc * sizeof(char *));
Comment 13 Chris Liddell (chrisl) 2013-08-30 03:11:07 UTC
Created attachment 10157 [details]
Simple display device test code

Yours has a fair amount missing, so I've attached a complete example, which can drop in replacing the existing psi\dwmainc.c source file.

You need to use the 64 bit Visual Studio command prompt, and build with:
nmake -f psi\msvc.mak DEVSTUDIO= BUILD_SYSTEM=64 WIN64=1 MAKEDLL=0

Running gswin64c.exe after that outputs:
GPL Ghostscript GIT PRERELEASE 9.10 (2013-08-14)
Copyright (C) 2013 Artifex Software, Inc.  All rights reserved.
This software comes with NO WARRANTY: see the file PUBLIC for details.
code = 0


Which is what I'd expect. So the setting of -sDisplayHandle=0 works as it should. So it would seem something about the C#->C/C++ binding is possibly the culprit. Is it possible the string is being converted to some Unicode variant, rather than being in plain ASCII. Possibly, you could build the GS DLL with the "GS_NO_UTF8=1" setting, thus:
nmake -f psi\msvc.mak DEVSTUDIO= BUILD_SYSTEM=64 WIN64=1 MAKEDLL=0 GS_NO_UTF8=1

again in the VS 64 bit tools command prompt window.
Comment 14 Josip Habjan 2013-08-30 07:56:03 UTC
Ken, the sample i posted was the sample from the current API doc.

Chris, thanks, you were right. I managed to solve my problem by setting aligning fields to the default packing size for the current platform for the display_device structure callback. 

32-bit works with A value of 1 indicates that data alignment occurs on byte boundaries. There are no gaps between fields with a packing value of 1.

Default is 0 that indicates that the packing alignment is set to the default for the current platform. 

Packing values of 2 and higher will cause each field to be aligned on a byte offset relative to the beginning of the structure. Therefore, data fields will start on offsets that are multiples of the requested packing value.

Thank you both.