Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

A simple GhostScript PS to PDF C++ DLL wrapper


:P
On this page:

Updated to work with GPL and AFPL versions for the reg lookup- 3/21/2005

I decided that West Wind Web Connection could use support for GhostScript today as part of its series of supported PDF drivers etc. GhostScript is open source so it's (sort of) free - as with all open source free, doesn't mean really free - commercial use still requires payment. GhostView provides a ton of functionality in dealing with PostScript and PDF manipulation. However, the one I have been interested in is PostScript to PDF conversion which allows you to basically print from any printer to a PostScript File and convert that file into a PDF document.

 

I have to say I’m always underwhelmed by the documentation of these open source kind of tools. The documentation is always messy and the examples always assume you want to compile the whole source tree, which in most cases is not at all what you want - I suspect most people just want to call into the existing functionality from their own applications. Digging around for a few integration samples turned up all sorts of huge projects that put wrappers for all functionality ontop of GhostScript.

 

My needs are a bit simpler: I simply want to call the GhostScript DLL – dynamically via a simple DLL interface without having to compile all of GhostScript into my wrapper DLL. I basically want to create a small wrapper DLL function that can be called via Interop from any language – specifically in my case from Visual FoxPro.

 

To do this I created this simple DLL function that I’ve now added to wwIPStuff.dll which already ships with West Wind Web Connection:

 

#include <windows.h>

 

BOOL WINAPI GhostPsToPdf(char *PsFile, char *PdfFile,

                         char *Resolution, char *PaperSize, char *GsDll )

{

      HMODULE hModule = NULL;

      char *DllPath;

 

      if (!GsDll)

      {

            HKEY hReg;

            char Path[MAX_PATH] ;

            DWORD Size = MAX_PATH;

                 

            char RegPath[MAX_PATH] = "SOFTWARE\\AFPL Ghostscript";

 

            if (RegOpenKey(HKEY_LOCAL_MACHINE,RegPath,&hReg) != ERROR_SUCCESS)

            {

                  strcpy(RegPath,"SOFTWARE\\GPL Ghostscript");

                  if (RegOpenKey(HKEY_LOCAL_MACHINE,RegPath,&hReg) != ERROR_SUCCESS)

                        return FALSE;

            }

           

            // *** Grab the first sub-key

            char Version[40]; // just to be safe

            DWORD VerSize=9;

            if (RegEnumKeyEx(hReg,0,Version,&VerSize,NULL,NULL,NULL,NULL) != ERROR_SUCCESS)

            {

                  RegCloseKey(hReg);

                  return FALSE;

            }

            RegCloseKey(hReg);

           

 

            // *** Add to the main path and open the subkey

            strcat(RegPath,"\\");

            strcat(RegPath,Version);

            if (RegOpenKey(HKEY_LOCAL_MACHINE,RegPath,&hReg) != ERROR_SUCCESS)

                  return FALSE;

     

            DWORD RegType = REG_SZ;

            if (RegQueryValueEx(hReg,"GS_DLL",0,&RegType,(LPBYTE) Path,&Size) != ERROR_SUCCESS)

            {

                  RegCloseKey(hReg);           

                  return FALSE;

            }

           

            DllPath = Path;

 

            RegCloseKey(hReg);

      }

      else

            DllPath = GsDll;

 

   hModule = LoadLibrary(DllPath);

   if (!hModule)

         return FALSE;

 

      if (!Resolution)

      {

            char cResolution[8] = "150x150";

            Resolution = cResolution;

      }

      char ArgPaperSize[50] = "-sPAPERSIZE=letter";

      if (PaperSize) 

      {

            strcpy(ArgPaperSize,"-sPAPERSIZE=");

            strcat(ArgPaperSize,PaperSize);

      }

 

     

     

   // *** Declare all the dynamic typedef function pointers

   typedef int (WINAPI *gsapi_new_instance)( char **, int );

   gsapi_new_instance lp_gsapi_new_instance ;

   lp_gsapi_new_instance = (gsapi_new_instance) GetProcAddress(hModule,"gsapi_new_instance");

 

   typedef int (WINAPI *gsapi_delete_instance) (char *);

   gsapi_delete_instance lp_gsapi_delete_instance;

   lp_gsapi_delete_instance = (gsapi_delete_instance) GetProcAddress(hModule,"gsapi_delete_instance");

 

   typedef int (WINAPI *gsapi_init_with_args) (char *,int,char *);

   gsapi_init_with_args lp_gsapi_init_with_args;

   lp_gsapi_init_with_args = (gsapi_init_with_args) GetProcAddress(hModule,"gsapi_init_with_args");

 

   typedef int (WINAPI *gsapi_exit) (char *);

   gsapi_exit lp_gsapi_exit;

   lp_gsapi_exit = (gsapi_exit) GetProcAddress(hModule,"gsapi_exit");

 

   char ArgResolution[80] = "-r";

   strcat(ArgResolution,Resolution);

 

   char ArgOutputFile[MAX_PATH + 16] = "-sOutputFile=";

   strcat(ArgOutputFile,PdfFile);

 

      // *** Set up the parameters to the engine 

    const char * gsargv[11];

    int gsargc;

    gsargv[0] = "PsToPdf";    /* actual value doesn't matter */

    gsargv[1] = "-dNOPAUSE";  // no prompts

    gsargv[2] = "-dBATCH";    // exit after processing

    gsargv[3] = "-dSAFER";    // Safe mode

      gsargv[4] = ArgResolution;

      gsargv[5] = ArgPaperSize;

      gsargv[6] = "-sDEVICE=pdfwrite"; 

      gsargv[7] = ArgOutputFile;

    gsargv[8] = "-c";

    gsargv[9] = ".setpdfwrite";

    gsargv[10] = "-f";

      gsargv[11] = PsFile;

    gsargc=12;

 

      // *** Simulate pointer to struct with plain char *

      char *Inst = NULL;

      int code = 0;

 

      code = (lp_gsapi_new_instance)(&Inst,NULL);

      if (code == 0)

      {

            // Do the conversion

            code = (lp_gsapi_init_with_args) (Inst,gsargc,(char *) gsargv );

            if (code == 0)

                  code = (lp_gsapi_exit) (Inst);

           

            // *** Release the handle

            (lp_gsapi_delete_instance) (Inst);

      }

 

      if (hModule)

            FreeLibrary(hModule);

 

      if (code == 0)

            return TRUE;

 

      return FALSE;

}

 

This code is obviously Windows specific since it uses the registry to figure out where the DLL lives. Note also that there’s a parameter to allow you to pass in the DLL name directly just in case the registry is not accessible (it requires Admin rights) or in case the registry entries aren’t there to start with.

 

Please excuse my sloppy C++ - whenever I do C++ I’m reminded that I’m soooo glad I don’t have to write C++ code and deal with pointers to pointers on a regular basis. Ughhh

 

Note in order for this to work you need to have GhostScript installed and you probably will want to install a Postscript printer (like the Apple Color LW 12/660 PS ) to print reports or documents to PostScript first.

FWIW, I also found some VFP code that does this all in native Fox code and ironically that’s what ultimately set me on the right path to creating the self-contained DLL code shown here. It's Print2PDF.prg, but heck I can’t find the damn Web link now and there’s no link reference in the source… Here’s an FTP site where you can download the code though - it includes the actual PDF conversion class as well as Ed Rauh's Heap class that deals with managing the parameter structure pointer in the above code.

 

I ended up not using the pure Fox code because it has some dependencies I didn’t want to pull into West Wind Web Connection and because this functionality is useful for other environments as well.

 

Hope this helps somebody out.

 


The Voices of Reason


 

Malcolm Greene
March 17, 2005

# re: A simple GhostScript PS to PDF C++ DLL wrapper

Rick,

Will the updated wwIPstuff.Dll you created for Web Connection be finding its way back to your wwIPstuff product?

I believe the print2pdf website you're looking for might be Bob Lee's

http://1amsoftware.com/Downloads.htm

Note the renamed files (vfp2pdf vs. print2pdf).

Malcolm

Bob Lee
March 17, 2005

# re: A simple GhostScript PS to PDF C++ DLL wrapper

On this site is both versions, The orig one I wrote which calls the ghostscript exe... not too clean. but it works, also the one based on my work which calls the ghostscript dll..

They work great for web servers or document processing where you need to name pdf files from vfp reports.


Bob Lee

Rick Strahl
March 17, 2005

# re: A simple GhostScript PS to PDF C++ DLL wrapper

Malcom: Yes eventually the Client Tools will get this stuff. wwIPStuff won't (well, at least not officially) since that product doesn't include the PDF classes.

Bob: Thanks for the link. I wasn't sure exactly who to give credit to because there were so many author notices yet no references to any Web Sites which was odd.

Somewhere I found an article that talked about what the code does. I think it was your's but I just can't find that link again.

Bob Lee
March 17, 2005

# re: A simple GhostScript PS to PDF C++ DLL wrapper

When I read the orig linux script ps2pdf and its version in dos.. it seemed so simple..
create a .ps file
pass the ps file into ghostscript with the correct parms.. and like magic anything you can make into a ps file, you could convert it to pdf. All Free. No acrobat needed.

That was where I stared.. using VFP to duplicate the orig linux script - or dos batch file..

But, to get it all working with loading dlls, it took more experience than I had.
Since then others have even taken it to convert word docs to pdf using VFP /GhostScript.
I think someone should rewrite it into a report listener function ? with VFP9.

Malcolm Greene
March 17, 2005

# re: A simple GhostScript PS to PDF C++ DLL wrapper

Ghostscript is a bear of a product that appears to include everything but the kitchen sink. Has anyone found a stripped down version of Ghostscript that JUST does Postscript to PDF conversion - period. I've been searching for such a build for awhile and haven't come across anything like this. I can't believe I'm not the only one looking for such a beast?

Malcolm

Rick Strahl
March 21, 2005

# re: A simple GhostScript PS to PDF C++ DLL wrapper

Malcom, I think you're going to need all that stuff that installs. Most of the stuff is resources used to handle font and image management. It's surely pretty integral to the install. Postscript parsing isn't trivial and neither is PDF creation.

Bob Lee
May 01, 2005

# re: A simple GhostScript PS to PDF C++ DLL wrapper

I think this page has what you are looking for.. Look at the converter ..
Bob Lee
bobl@1amsoftware.com

Tran Thanh Phong
June 09, 2005

# re: A simple GhostScript PS to PDF C++ DLL wrapper

But if I want to use gsdll32.dll, How to make it to convert EPS --> JPG in ASP.NET?

Satya
June 21, 2005

# re: A simple GhostScript PS to PDF C++ DLL wrapper

Is ghostscript is supported for HP-UNIX,AIX,Irix,Solaris And Linux

Manmohan Singh Sarwara
July 13, 2005

# I Need Vice-Versa

I am battling with a Idea of Converting .PDF Document To a simple Text Document. I got a lot of support regarding it but all is in the shape of Dll or COM Component so i cannot customize tha t code according to my specification as sometimes i face problem is packing these components while making Installers. It will be a great support to me if you supply some similar code to convert PDF file into Text File in a simple and minimal lines of programming Codes.
mohans@exeige.com

konda reddy
September 25, 2005

# re: A simple GhostScript PS to PDF COM Component

Hi,
In my project i need to convert PDF file to JPG image, in google i found your DLL will do this process, can you pls help me in this regard.
I need a component where i can covert PDF file to a JPG image file.


Thanks in advance,
Konda.

Govardhan
April 12, 2006

# re: A simple GhostScript PS to PDF C++ DLL wrapper

Hi,

I want to know whether can i use this in C#.Net application. I wanted use the feature where in i can convert a .ps file to pdf file or to a .txt file. SO i wanted to know whether is it possible for me to use this.

Govardhan

Rick Strahl
April 12, 2006

# re: A simple GhostScript PS to PDF C++ DLL wrapper

If you compile this into a Windows DLL you can call it with PInvoke interop.


ISaqib Jillani
August 11, 2006

# re: A simple GhostScript PS to PDF C++ DLL wrapper

I used this code and it gives this message
"unable to open initial device, quitting" I have AFPL GhostScript 8.54 installed .Is it caused by that i don't have a Postscript printer installed what should to do instead I want to convert a given Post script file to a pdf file

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024