实现用C#和VB.NET调用Ghostscript的API,把Postscript文件转为PDF文件。

简介:
利用 Ghostscript提供的gsapi_vb实现转postscript为PDF,进一步成功把VB.NET代码转为C#。
所用GhostScript为AFPL Ghostscript 8.53
附上GhostScript提供的VB.NET代码:

None.gif' Copyright (c) 2002 Dan Mount and Ghostgum Software Pty Ltd
None.gif'
None.gif'
 Permission is hereby granted, free of charge, to any person obtaining 
None.gif'
 a copy of this software and associated documentation files (the 
None.gif'
 "Software"), to deal in the Software without restriction, including
None.gif'
 without limitation the rights to use, copy, modify, merge, publish, 
None.gif'
 distribute, sublicense, and/or sell copies of the Software, and to
None.gif'
 permit persons to whom the Software is furnished to do so, subject to 
None.gif'
 the following conditions:
None.gif'
None.gif'
 The above copyright notice and this permission notice shall be
None.gif'
 included in all copies or substantial portions of the Software.
None.gif'
None.gif'
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
None.gif'
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
None.gif'
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
None.gif'
 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
None.gif'
 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 
None.gif'
 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
None.gif'
 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
None.gif'
 SOFTWARE.
None.gif

None.gif
None.gif
' This is an example of how to call the Ghostscript DLL from
None.gif'
 Visual Basic.NET.  There are two examples, one converts
None.gif'
 colorcir.ps to PDF, the other is like command line Ghostscript.
None.gif'
 The display device is not supported.
None.gif'
None.gif'
 This code is not compatible with VB6.  There is another
None.gif'
 example which does work with VB6.  Differences include:
None.gif'
 1. VB.NET uses GCHandle to get pointer
None.gif'
    VB6 uses StrPtr/VarPtr
None.gif'
 2. VB.NET Integer is 32bits, Long is 64bits
None.gif'
    VB6 Integer is 16bits, Long is 32bits
None.gif'
 3. VB.NET uses IntPtr for pointers
None.gif'
    VB6 uses Long for pointers
None.gif'
 4. VB.NET strings are always Unicode
None.gif'
    VB6 can create an ANSI string
None.gif'
 See the following URL for some VB6 / VB.NET details
None.gif'
  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvb600/html/vb6tovbdotnet.asp
None.gif

None.gif
Option Explicit On 
None.gif
None.gif
Imports System.Runtime.InteropServices
None.gif
ExpandedBlockStart.gifContractedBlock.gif
Module gsapiModule gsapi
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
Public Declare Sub CopyMemory()Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByVal dest As IntPtr, ByVal source As IntPtr, ByVal bytes As Long)
InBlock.gif
InBlock.gif    
'------------------------------------------------
InBlock.gif
    'UDTs Start
InBlock.gif
    '------------------------------------------------
ExpandedSubBlockStart.gifContractedSubBlock.gif
    <StructLayout(LayoutKind.Sequential)> Public Structure GS_RevisionStructure GS_Revision
InBlock.gif        
Public strProduct As IntPtr
InBlock.gif        
Public strCopyright As IntPtr
InBlock.gif        
Public intRevision As Integer
InBlock.gif        
Public intRevisionDate As Integer
ExpandedSubBlockEnd.gif    
End Structure

InBlock.gif    
'------------------------------------------------
InBlock.gif
    'UDTs End
InBlock.gif
    '------------------------------------------------
InBlock.gif

InBlock.gif    
'------------------------------------------------
InBlock.gif
    'Callback Functions Start
InBlock.gif
    '------------------------------------------------
InBlock.gif
    'These are only required if you use gsapi_set_stdio
ExpandedSubBlockStart.gifContractedSubBlock.gif
    Public Delegate Function StdioCallBack()Function StdioCallBack(ByVal handle As IntPtr, ByVal strptr As IntPtr, ByVal count As IntegerAs Integer
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
Public Function gsdll_stdin()Function gsdll_stdin(ByVal intGSInstanceHandle As IntPtr, ByVal strz As IntPtr, ByVal intBytes As IntegerAs Integer
InBlock.gif        
' This is dumb code that reads one byte at a time
InBlock.gif
        ' Ghostscript doesn't mind this, it is just very slow
InBlock.gif
        If intBytes = 0 Then
InBlock.gif            gsdll_stdin 
= 0
InBlock.gif        
Else
InBlock.gif            
Dim ich As Integer = Console.Read()
InBlock.gif            
If ich = -1 Then
InBlock.gif                gsdll_stdin 
= 0 ' EOF
InBlock.gif
            Else
InBlock.gif                
Dim bch As Byte = ich
InBlock.gif                
Dim gcByte As GCHandle = GCHandle.Alloc(bch, GCHandleType.Pinned)
InBlock.gif                
Dim ptrByte As IntPtr = gcByte.AddrOfPinnedObject()
InBlock.gif                CopyMemory(strz, ptrByte, 
1)
InBlock.gif                ptrByte 
= IntPtr.Zero
InBlock.gif                gcByte.Free()
InBlock.gif                gsdll_stdin 
= 1
InBlock.gif            
End If
InBlock.gif        
End If
ExpandedSubBlockEnd.gif    
End Function

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
Public Function gsdll_stdout()Function gsdll_stdout(ByVal intGSInstanceHandle As IntPtr, ByVal strz As IntPtr, ByVal intBytes As IntegerAs Integer
InBlock.gif        
' If you can think of a more efficient method, please tell me!
InBlock.gif
        ' We need to convert from a byte buffer to a string
InBlock.gif
        ' First we create a byte array of the appropriate size
InBlock.gif
        Dim aByte(intBytes) As Byte
InBlock.gif        
' Then we get the address of the byte array
InBlock.gif
        Dim gcByte As GCHandle = GCHandle.Alloc(aByte, GCHandleType.Pinned)
InBlock.gif        
Dim ptrByte As IntPtr = gcByte.AddrOfPinnedObject()
InBlock.gif        
' Then we copy the buffer to the byte array
InBlock.gif
        CopyMemory(ptrByte, strz, intBytes)
InBlock.gif        
' Release the address locking
InBlock.gif
        ptrByte = IntPtr.Zero
InBlock.gif        gcByte.Free()
InBlock.gif        
' Then we copy the byte array to a string, character by character
InBlock.gif
        Dim str As String
InBlock.gif        
Dim i As Integer
InBlock.gif        
For i = 0 To intBytes - 1
InBlock.gif            
str = str + Chr(aByte(i))
InBlock.gif        
Next
InBlock.gif        
' Finally we output the message
InBlock.gif
        Console.Write(str)
InBlock.gif        gsdll_stdout 
= intBytes
ExpandedSubBlockEnd.gif    
End Function

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
Public Function gsdll_stderr()Function gsdll_stderr(ByVal intGSInstanceHandle As IntPtr, ByVal strz As IntPtr, ByVal intBytes As IntegerAs Integer
InBlock.gif        gsdll_stderr 
= gsdll_stdout(intGSInstanceHandle, strz, intBytes)
ExpandedSubBlockEnd.gif    
End Function

InBlock.gif    
'------------------------------------------------
InBlock.gif
    'Callback Functions End
InBlock.gif
    '------------------------------------------------
InBlock.gif

InBlock.gif    
'------------------------------------------------
InBlock.gif
    'API Calls Start
InBlock.gif
    '------------------------------------------------
InBlock.gif
    'Win32 API
InBlock.gif
    'GhostScript API
InBlock.gif
    '    Public Declare Function gsapi_revision Lib "gsdll32.dll" (ByVal pGSRevisionInfo As IntPtr, ByVal intLen As Integer) As Integer
ExpandedSubBlockStart.gifContractedSubBlock.gif
    Public Declare Function gsapi_revision()Function gsapi_revision Lib "gsdll32.dll" (ByRef pGSRevisionInfo As GS_Revision, ByVal intLen As IntegerAs Integer
ExpandedSubBlockStart.gifContractedSubBlock.gif    
Public Declare Function gsapi_new_instance()Function gsapi_new_instance Lib "gsdll32.dll" (ByRef lngGSInstance As IntPtr, ByVal lngCallerHandle As IntPtr) As Integer
ExpandedSubBlockStart.gifContractedSubBlock.gif    
Public Declare Function gsapi_set_stdio()Function gsapi_set_stdio Lib "gsdll32.dll" (ByVal lngGSInstance As IntPtr, ByVal gsdll_stdin As StdioCallBack, ByVal gsdll_stdout As StdioCallBack, ByVal gsdll_stderr As StdioCallBack) As Integer
ExpandedSubBlockStart.gifContractedSubBlock.gif    
Public Declare Sub gsapi_delete_instance()Sub gsapi_delete_instance Lib "gsdll32.dll" (ByVal lngGSInstance As IntPtr)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
Public Declare Function gsapi_init_with_args()Function gsapi_init_with_args Lib "gsdll32.dll" (ByVal lngGSInstance As IntPtr, ByVal lngArgumentCount As IntegerByVal lngArguments As IntPtr) As Integer
ExpandedSubBlockStart.gifContractedSubBlock.gif    
Public Declare Function gsapi_run_file()Function gsapi_run_file Lib "gsdll32.dll" (ByVal lngGSInstance As IntPtr, ByVal strFileName As StringByVal intErrors As IntegerByVal intExitCode As IntegerAs Integer
ExpandedSubBlockStart.gifContractedSubBlock.gif    
Public Declare Function gsapi_exit()Function gsapi_exit Lib "gsdll32.dll" (ByVal lngGSInstance As IntPtr) As Integer
InBlock.gif    
'------------------------------------------------
InBlock.gif
    'API Calls End
InBlock.gif
    '------------------------------------------------
InBlock.gif

InBlock.gif    
'------------------------------------------------
InBlock.gif
    'User Defined Functions Start
InBlock.gif
    '------------------------------------------------
ExpandedSubBlockStart.gifContractedSubBlock.gif
    Public Function StringToAnsiZ()Function StringToAnsiZ(ByVal str As StringAs Byte()
InBlock.gif        
' Convert a Unicode string to a null terminated Ansi string for Ghostscript.
InBlock.gif
        ' The result is stored in a byte array.  Later you will need to convert
InBlock.gif
        ' this byte array to a pointer with GCHandle.Alloc(XXXX, GCHandleType.Pinned)
InBlock.gif
        ' and GSHandle.AddrOfPinnedObject()
InBlock.gif
        Dim intElementCount As Integer
InBlock.gif        
Dim intCounter As Integer
InBlock.gif        
Dim aAnsi() As Byte
InBlock.gif        
Dim bChar As Byte
InBlock.gif        intElementCount 
= Len(str)
InBlock.gif        
ReDim aAnsi(intElementCount + 1)
InBlock.gif        
For intCounter = 0 To intElementCount - 1
InBlock.gif            bChar 
= Asc(Mid(str, intCounter + 11))
InBlock.gif            aAnsi(intCounter) 
= bChar
InBlock.gif        
Next intCounter
InBlock.gif        aAnsi(intElementCount) 
= 0
InBlock.gif        StringToAnsiZ 
= aAnsi
ExpandedSubBlockEnd.gif    
End Function

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
Public Function AnsiZtoString()Function AnsiZtoString(ByVal strz As IntPtr) As String
InBlock.gif        
' We need to convert from a byte buffer to a string
InBlock.gif
        Dim byteCh(1As Byte
InBlock.gif        
Dim bOK As Boolean = True
InBlock.gif        
Dim gcbyteCh As GCHandle = GCHandle.Alloc(byteCh, GCHandleType.Pinned)
InBlock.gif        
Dim ptrByte As IntPtr = gcbyteCh.AddrOfPinnedObject()
InBlock.gif        
Dim j As Integer = 0
InBlock.gif        
Dim str As String
InBlock.gif        
While bOK
InBlock.gif            
' This is how to do pointer arithmetic!
InBlock.gif
            Dim sPtr As New IntPtr(strz.ToInt64() + j)
InBlock.gif            CopyMemory(ptrByte, sPtr, 
1)
InBlock.gif            
If byteCh(0= 0 Then
InBlock.gif                bOK 
= False
InBlock.gif            
Else
InBlock.gif                
str = str + Chr(byteCh(0))
InBlock.gif            
End If
InBlock.gif            j 
= j + 1
InBlock.gif        
End While
InBlock.gif        AnsiZtoString 
= str
ExpandedSubBlockEnd.gif    
End Function

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
Public Function CheckRevision()Function CheckRevision(ByVal intRevision As IntegerAs Boolean
InBlock.gif        
' Check revision number of Ghostscript
InBlock.gif
        Dim intReturn As Integer
InBlock.gif        
Dim udtGSRevInfo As GS_Revision
InBlock.gif        
Dim gcRevision As GCHandle
InBlock.gif        gcRevision 
= GCHandle.Alloc(udtGSRevInfo, GCHandleType.Pinned)
InBlock.gif        intReturn 
= gsapi_revision(udtGSRevInfo, 16)
InBlock.gif        Console.WriteLine(
"Revision = " & udtGSRevInfo.intRevision)
InBlock.gif        Console.WriteLine(
"RevisionDate = " & udtGSRevInfo.intRevisionDate)
InBlock.gif        Console.WriteLine(
"Product = " & AnsiZtoString(udtGSRevInfo.strProduct))
InBlock.gif        Console.WriteLine(
"Copyright = " & AnsiZtoString(udtGSRevInfo.strCopyright))
InBlock.gif
InBlock.gif        
If udtGSRevInfo.intRevision = intRevision Then
InBlock.gif            CheckRevision 
= True
InBlock.gif        
Else
InBlock.gif            CheckRevision 
= False
InBlock.gif        
End If
InBlock.gif        gcRevision.Free()
ExpandedSubBlockEnd.gif    
End Function

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
Public Function CallGS()Function CallGS(ByVal astrGSArgs() As StringAs Boolean
InBlock.gif        
Dim intReturn As Integer
InBlock.gif        
Dim intGSInstanceHandle As IntPtr
InBlock.gif        
Dim aAnsiArgs() As Object
InBlock.gif        
Dim aPtrArgs() As IntPtr
InBlock.gif        
Dim aGCHandle() As GCHandle
InBlock.gif        
Dim intCounter As Integer
InBlock.gif        
Dim intElementCount As Integer
InBlock.gif        
Dim iTemp As Integer
InBlock.gif        
Dim callerHandle As IntPtr
InBlock.gif        
Dim gchandleArgs As GCHandle
InBlock.gif        
Dim intptrArgs As IntPtr
InBlock.gif
InBlock.gif        
' Print out the revision details.
InBlock.gif
        ' If we want to insist on a particular version of Ghostscript
InBlock.gif
        ' we should check the return value of CheckRevision().
InBlock.gif
        CheckRevision(704)
InBlock.gif
InBlock.gif        
' Load Ghostscript and get the instance handle
InBlock.gif
        intReturn = gsapi_new_instance(intGSInstanceHandle, callerHandle)
InBlock.gif        
If (intReturn < 0Then
InBlock.gif            
Return (False)
InBlock.gif        
End If
InBlock.gif
InBlock.gif        
' Capture stdio
InBlock.gif
        Dim stdinCallback As StdioCallBack
InBlock.gif        stdinCallback 
= AddressOf gsdll_stdin
InBlock.gif        
Dim stdoutCallback As StdioCallBack
InBlock.gif        stdoutCallback 
= AddressOf gsdll_stdout
InBlock.gif        
Dim stderrCallback As StdioCallBack
InBlock.gif        stderrCallback 
= AddressOf gsdll_stderr
InBlock.gif        intReturn 
= gsapi_set_stdio(intGSInstanceHandle, stdinCallback, stdoutCallback, stderrCallback)
InBlock.gif
InBlock.gif        
If (intReturn >= 0Then
InBlock.gif            
' Convert the Unicode strings to null terminated ANSI byte arrays
InBlock.gif
            ' then get pointers to the byte arrays.
InBlock.gif
            intElementCount = UBound(astrGSArgs)
InBlock.gif            
ReDim aAnsiArgs(intElementCount)
InBlock.gif            
ReDim aPtrArgs(intElementCount)
InBlock.gif            
ReDim aGCHandle(intElementCount)
InBlock.gif            
For intCounter = 0 To intElementCount
InBlock.gif                aAnsiArgs(intCounter) 
= StringToAnsiZ(astrGSArgs(intCounter))
InBlock.gif                aGCHandle(intCounter) 
= GCHandle.Alloc(aAnsiArgs(intCounter), GCHandleType.Pinned)
InBlock.gif                aPtrArgs(intCounter) 
= aGCHandle(intCounter).AddrOfPinnedObject()
InBlock.gif            
Next
InBlock.gif            gchandleArgs 
= GCHandle.Alloc(aPtrArgs, GCHandleType.Pinned)
InBlock.gif            intptrArgs 
= gchandleArgs.AddrOfPinnedObject()
InBlock.gif            callerHandle 
= IntPtr.Zero
InBlock.gif
InBlock.gif            intReturn 
= gsapi_init_with_args(intGSInstanceHandle, intElementCount + 1, intptrArgs)
InBlock.gif
InBlock.gif            
' Release the pinned memory
InBlock.gif
            For intCounter = 0 To intElementCount
InBlock.gif                aGCHandle(intCounter).Free()
InBlock.gif            
Next
InBlock.gif            gchandleArgs.Free()
InBlock.gif
InBlock.gif            
' Stop the Ghostscript interpreter
InBlock.gif
            gsapi_exit(intGSInstanceHandle)
InBlock.gif        
End If
InBlock.gif
InBlock.gif        
' release the Ghostscript instance handle
InBlock.gif
        gsapi_delete_instance(intGSInstanceHandle)
InBlock.gif
InBlock.gif        
If (intReturn >= 0Then
InBlock.gif            CallGS 
= True
InBlock.gif        
Else
InBlock.gif            CallGS 
= False
InBlock.gif        
End If
InBlock.gif
ExpandedSubBlockEnd.gif    
End Function

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
Private Function ConvertFile()Function ConvertFile() As Boolean
InBlock.gif        
Dim astrArgs(10As String
InBlock.gif        astrArgs(
0= "ps2pdf" 'The First Parameter is Ignored
InBlock.gif
        astrArgs(1= "-dNOPAUSE"
InBlock.gif        astrArgs(
2= "-dBATCH"
InBlock.gif        astrArgs(
3= "-dSAFER"
InBlock.gif        astrArgs(
4= "-r300"
InBlock.gif        astrArgs(
5= "-sDEVICE=pdfwrite"
InBlock.gif        astrArgs(
6= "-sOutputFile=c:\out.pdf"
InBlock.gif        astrArgs(
7= "-c"
InBlock.gif        astrArgs(
8= ".setpdfwrite"
InBlock.gif        astrArgs(
9= "-f"
InBlock.gif        astrArgs(
10= "c:\gs\gs7.04\examples\colorcir.ps"
InBlock.gif        
Return CallGS(astrArgs)
ExpandedSubBlockEnd.gif    
End Function

InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif    
Private Function InteractiveGS()Function InteractiveGS() As Boolean
InBlock.gif        
Dim astrArgs(2As String
InBlock.gif        astrArgs(
0= "gs" 'The First Parameter is Ignored
InBlock.gif
        astrArgs(1= "-c"
InBlock.gif        astrArgs(
2= "systemdict /start get exec"
InBlock.gif        
Return CallGS(astrArgs)
ExpandedSubBlockEnd.gif    
End Function

InBlock.gif
InBlock.gif
InBlock.gif    
'------------------------------------------------
InBlock.gif
    'User Defined Functions End
InBlock.gif
    '------------------------------------------------
InBlock.gif

ExpandedSubBlockStart.gifContractedSubBlock.gif    
Sub Main()Sub Main()
InBlock.gif        ConvertFile()
InBlock.gif        
'InteractiveGS()
InBlock.gif
        MsgBox("Done")
ExpandedSubBlockEnd.gif    
End Sub

InBlock.gif
ExpandedBlockEnd.gif
End Module

 

 

本文转自RubyPdf 的中文博客博客园博客,原文链接:http://www.cnblogs.com/hardrock/archive/2006/03/01/340580.html,如需转载请自行联系原作http://www.cnblogs.com/hardrock/archive/2006/05/17/402654.html

 

相关文章
|
17天前
|
数据可视化 网络协议 C#
C#/.NET/.NET Core优秀项目和框架2024年3月简报
公众号每月定期推广和分享的C#/.NET/.NET Core优秀项目和框架(每周至少会推荐两个优秀的项目和框架当然节假日除外),公众号推文中有项目和框架的介绍、功能特点、使用方式以及部分功能截图等(打不开或者打开GitHub很慢的同学可以优先查看公众号推文,文末一定会附带项目和框架源码地址)。注意:排名不分先后,都是十分优秀的开源项目和框架,每周定期更新分享(欢迎关注公众号:追逐时光者,第一时间获取每周精选分享资讯🔔)。
|
1月前
|
XML C# 数据格式
使用C#操作XML文件
使用C#操作XML文件
11 0
|
1月前
|
C#
C# 文件操作(全部) 追加、拷贝、删除、移动文件、创建目录
C# 文件操作(全部) 追加、拷贝、删除、移动文件、创建目录
23 0
|
1月前
|
数据挖掘 数据安全/隐私保护 开发者
使用Spire.PDF for Python插件从PDF文件提取文字和图片信息
使用Spire.PDF for Python插件从PDF文件提取文字和图片信息
75 0
|
1月前
|
存储 缓存 Python
如何使用Python抓取PDF文件并自动下载到本地
如何使用Python抓取PDF文件并自动下载到本地
34 0
|
1月前
|
SQL 数据库 C#
C# .NET面试系列十一:数据库SQL查询(附建表语句)
#### 第1题 用一条 SQL 语句 查询出每门课都大于80 分的学生姓名 建表语句: ```sql create table tableA ( name varchar(10), kecheng varchar(10), fenshu int(11) ) DEFAULT CHARSET = 'utf8'; ``` 插入数据 ```sql insert into tableA values ('张三', '语文', 81); insert into tableA values ('张三', '数学', 75); insert into tableA values ('李四',
65 2
C# .NET面试系列十一:数据库SQL查询(附建表语句)
|
1月前
|
开发框架 算法 搜索推荐
C# .NET面试系列九:常见的算法
#### 1. 求质数 ```c# // 判断一个数是否为质数的方法 public static bool IsPrime(int number) { if (number < 2) { return false; } for (int i = 2; i <= Math.Sqrt(number); i++) { if (number % i == 0) { return false; } } return true; } class Progr
58 1
|
6天前
|
XML C# 数据格式
C# 解析XML文件
C# 解析XML文件
15 1
|
10天前
|
开发框架 前端开发 JavaScript
采用C#.Net +JavaScript 开发的云LIS系统源码 二级医院应用案例有演示
技术架构:Asp.NET CORE 3.1 MVC + SQLserver + Redis等 开发语言:C# 6.0、JavaScript 前端框架:JQuery、EasyUI、Bootstrap 后端框架:MVC、SQLSugar等 数 据 库:SQLserver 2012
|
1月前
|
安全 数据处理 C#
C# Post数据或文件到指定的服务器进行接收
C# Post数据或文件到指定的服务器进行接收