Ok, deep breath everyone... And it's long(ish) as well, sorry.
I'm writing (have pretty much written) an application that uses the Ghostscript DLL's - an implementation of a Postscript interpreter - to convert Postscript files to TIFF Image files.
The Ghostscript (GS) DLL functions are defined in VB like this:
[tt]
Private Declare Function gsdll_init Lib "gsdll32.dll" ( _
ByVal lpGsBack As Any, _
ByVal hwnd As Long, _
ByVal argc As Long, _
Argv As Long _
) As Integer
Private Declare Function gsdll_execute_begin Lib "gsdll32.dll" () As Integer
Private Declare Function gsdll_execute_cont Lib "gsdll32.dll" ( _
ByVal pscommand As String, _
ByVal commlen As Long _
) As Integer
Private Declare Function gsdll_execute_end Lib "gsdll32.dll" () As Integer
Private Declare Function gsdll_exit Lib "gsdll32.dll" () As Integer
[/tt]
The VB code calling these functions looks like this:
[tt]
[tab]rcode = gsdll_init(AddressOf Callback, f.hwnd, 8, llaArgV(0))
[tab]If (rcode = 0) Then
[tab][tab]rcode = gsdll_execute_begin()
[tab][tab]If (rcode = 0) Then
[tab][tab][tab]gsdll_execute_end
[tab][tab][tab]gsdll_exit
[tab][tab]Else
[tab][tab][tab]f.lstLog.AddItem "ERROR: rcode = " & rcode & " after gsdll_execute_begin"
[tab][tab][tab]rcode = gsdll_exit()
[tab][tab][tab]f.lstLog.AddItem "ERROR: rcode = " & rcode & " after gsdll_exit"
[tab][tab][tab]lsRetVal = vbNullString
[tab][tab][tab]Exit Function
[tab][tab]End If
[tab]Else
[tab][tab]f.lstLog.AddItem "ERROR: rcode = " & rcode & " after gsdll_init"
[tab][tab]lsRetVal = vbNullString
[tab][tab]Exit Function
[tab]End If
[/tt]
The good news is -- it works pretty well.
The bad news is -- when it doesn't it's pretty bad.....
You might have spotted the following line in the code above, it's where my problems start:
[tt]
gsdll_init(AddressOf Callback, f.hwnd, 8, llaArgV(0))
[/tt]
GS needs the address of a subroutine in my application (Callback), it uses this subroutine to inform me of its progress, any syntax problems it finds in the .PS file or problems in the parameters I've passed to gsdll_init. The parameters, inc the name of the file to be processed and the name of the output file, are passed in llaArgV(0).
The GS documentation specifies that the callback subroutine should be defined as:
[tt]
int gsdll_callback(int message, char *str, unsigned long count)
[/tt]
and gives some nice instructions on how to interpret the messages that will arrive. It also states that the Pascal calling convention is not used, which I don't know the details of but am aware that it has to do with the order in which arguments are placed on the stack.
All well and good, I'm sure it's just dandy when you're calling it from a C or C++ program; but I'm not.
I translate the C prototype above into the following VB definition:
[tt]
Private Function Callback(msgnum As Long, sptr As Long, slen As Long) As Long
[/tt]
This does not work. I get stack overflows, NT complaining that the data at so-and-so could not be 'read', general unhappiness.
If I define the function like this it works:
[tt]
Private Function Callback() As Long
[tab]Callback = 0
End Function
[/tt]
But I don't get access to the error messages produced by GS and I need them. Some error conditions require that the gsdll_exit() be called and others that it must *not* be called. This application will run unattended -- so it needs to cope on its own.
The people who write and maintain GS said "let us have a copy of the code when you get it working", which I suppose show's they're interested but doesn't help me.
I would appreciate any thoughts and comments you might have.
I am, of course, happy to post the results, source code and anything else people might find useful once the application is working.
Regards,
Mike
michael.j.lacey@ntlworld.com
Email welcome if you're in a hurry or something -- but post in tek-tips as well please, and I will post my reply here as well.
I'm writing (have pretty much written) an application that uses the Ghostscript DLL's - an implementation of a Postscript interpreter - to convert Postscript files to TIFF Image files.
The Ghostscript (GS) DLL functions are defined in VB like this:
[tt]
Private Declare Function gsdll_init Lib "gsdll32.dll" ( _
ByVal lpGsBack As Any, _
ByVal hwnd As Long, _
ByVal argc As Long, _
Argv As Long _
) As Integer
Private Declare Function gsdll_execute_begin Lib "gsdll32.dll" () As Integer
Private Declare Function gsdll_execute_cont Lib "gsdll32.dll" ( _
ByVal pscommand As String, _
ByVal commlen As Long _
) As Integer
Private Declare Function gsdll_execute_end Lib "gsdll32.dll" () As Integer
Private Declare Function gsdll_exit Lib "gsdll32.dll" () As Integer
[/tt]
The VB code calling these functions looks like this:
[tt]
[tab]rcode = gsdll_init(AddressOf Callback, f.hwnd, 8, llaArgV(0))
[tab]If (rcode = 0) Then
[tab][tab]rcode = gsdll_execute_begin()
[tab][tab]If (rcode = 0) Then
[tab][tab][tab]gsdll_execute_end
[tab][tab][tab]gsdll_exit
[tab][tab]Else
[tab][tab][tab]f.lstLog.AddItem "ERROR: rcode = " & rcode & " after gsdll_execute_begin"
[tab][tab][tab]rcode = gsdll_exit()
[tab][tab][tab]f.lstLog.AddItem "ERROR: rcode = " & rcode & " after gsdll_exit"
[tab][tab][tab]lsRetVal = vbNullString
[tab][tab][tab]Exit Function
[tab][tab]End If
[tab]Else
[tab][tab]f.lstLog.AddItem "ERROR: rcode = " & rcode & " after gsdll_init"
[tab][tab]lsRetVal = vbNullString
[tab][tab]Exit Function
[tab]End If
[/tt]
The good news is -- it works pretty well.
The bad news is -- when it doesn't it's pretty bad.....
You might have spotted the following line in the code above, it's where my problems start:
[tt]
gsdll_init(AddressOf Callback, f.hwnd, 8, llaArgV(0))
[/tt]
GS needs the address of a subroutine in my application (Callback), it uses this subroutine to inform me of its progress, any syntax problems it finds in the .PS file or problems in the parameters I've passed to gsdll_init. The parameters, inc the name of the file to be processed and the name of the output file, are passed in llaArgV(0).
The GS documentation specifies that the callback subroutine should be defined as:
[tt]
int gsdll_callback(int message, char *str, unsigned long count)
[/tt]
and gives some nice instructions on how to interpret the messages that will arrive. It also states that the Pascal calling convention is not used, which I don't know the details of but am aware that it has to do with the order in which arguments are placed on the stack.
All well and good, I'm sure it's just dandy when you're calling it from a C or C++ program; but I'm not.
I translate the C prototype above into the following VB definition:
[tt]
Private Function Callback(msgnum As Long, sptr As Long, slen As Long) As Long
[/tt]
This does not work. I get stack overflows, NT complaining that the data at so-and-so could not be 'read', general unhappiness.
If I define the function like this it works:
[tt]
Private Function Callback() As Long
[tab]Callback = 0
End Function
[/tt]
But I don't get access to the error messages produced by GS and I need them. Some error conditions require that the gsdll_exit() be called and others that it must *not* be called. This application will run unattended -- so it needs to cope on its own.
The people who write and maintain GS said "let us have a copy of the code when you get it working", which I suppose show's they're interested but doesn't help me.
I would appreciate any thoughts and comments you might have.
I am, of course, happy to post the results, source code and anything else people might find useful once the application is working.
Regards,
Mike
michael.j.lacey@ntlworld.com
Email welcome if you're in a hurry or something -- but post in tek-tips as well please, and I will post my reply here as well.