Jump to content

Autoit DllCall and GhostScript issue


Go to solution Solved by Danyfirex,

Recommended Posts

Hi all,

I've spent hours poring over the forums to try and find similar examples to mine, but still managed to get stuck at a particular point in the process to invoke the gsdll32.dll functions. I am able to open the DLL, and get a successful response from gsapi_new_instance when passing pointers around there. However, attempting to invoke gsapi_init_with_args has me very frustrated. Here's my code:

Local $aDllArgs[9] = ["gswin32c", _
                                 "-sDEVICE=pdfwrite", _
                                 "-dNOPAUSE", _
                                 "-dBATCH", _
                                 "-dSAFER", _
                                 "-dFirstPage=" & $aParseArgs[3], _
                                 "-dLastPage=" & $aParseArgs[4], _
                                 "-sOutputFile=""" & $sDestName & """", _
                                 """" & $sPDFPath & """"]


            $varList = DllStructCreate("ptr[" & UBound($aDllArgs) & "]")
            $p_varList = DllStructGetPtr($varList)


            For $k=1 to UBound($aDllArgs)
               DllStructSetData( $varList, _
                                 $k, _
                                 DllStructSetData(DllStructCreate("char[255]"), 1, $aDllArgs[$k-1]))
            Next

            consolewrite("varList is located at: " & $p_varList & @CRLF)

            Local $hDll = DllOpen(@ScriptDir & "\gsdll32.dll")

            Local $hInst
            ConsoleWrite("hInst prior to call: " & $hInst & @CRLF)
            Local $dResult = DllCall($hDll, "int", "gsapi_new_instance", "ptr*", Null, "ptr", Null)

            $hInst = $dResult[1]

            ConsoleWrite("created instance. returned: " & $dResult[0] & @CRLF & "$hInst: " & $hInst & @CRLF)
            If $dResult[0] = 0 Then
               ConsoleWrite("trying to print PDF" & @CRLF)
               $dResult = DllCall($hDll, "int", "gsapi_init_with_args", "ptr", $hInst, _
                                 "int", UBound($aDllArgs), _
                                 "ptr", $p_varList)

Since gsapi_init_with_args takes (void *instance, int argc, char **argv), I figured I needed to convert the items in my $aDllArgs array to DllStructs, then pass the pointer to that DllStruct into the function call since AutoIt doesn't have char** types. Unfortunately this just crashes out once the code reaches this line.

However, even when I tried passing the third argument as type "str" or "str*" and $aDllArgs directly:

$dResult = DllCall($hDll, "int", "gsapi_init_with_args", "ptr", $hInst, _
                                 "int", UBound($aDllArgs), _
                                 "str*", $aDllArgs)

it still crashes out.

Not sure where to go from here. Any help would be greatly appreciated.

Thanks.

Link to comment
Share on other sites

Have you checked if $varList contains the proper data? (Hint: You have only one element, which is an array of pointers.)

Edited by LarsJ
Link to comment
Share on other sites

  • Solution

Edit 1. I was Wrong. maybe if you try the C code. then can make it in autoit.

Edit 2:

$dResult = DllCall($hDll, "int", "gsapi_init_with_args", "ptr", $hInst,  "int", UBound($aDllArgs),    "str*", $aDllArgs)

 

last dllcall argument should be a pointer to structure $p_varList.

look:

$dResult = DllCall($hDll, "int", "gsapi_init_with_args", "ptr", $hInst,"int",UBound($aDllArgs), "ptr", $p_varList)

Saludos

 

Edit 3

Your structure of pointers is wrong. Try something like this:

Local $aDllArgs[9] = ["gswin32c", _
                                 "-sDEVICE=pdfwrite", _
                                 "-dNOPAUSE", _
                                 "-dBATCH", _
                                 "-dSAFER", _
                                 "-dFirstPage=" & $aParseArgs[3], _
                                 "-dLastPage=" & $aParseArgs[4], _
                                 "-sOutputFile=""" & $sDestName & """", _
                                 """" & $sPDFPath & """"]
   
   
   
   
   $varList = DllStructCreate("ptr[" & UBound($aDllArgs) & "]")
            $p_varList = DllStructGetPtr($varList)


         Local $tData[UBound($aDllArgs)]

            for $i= 1 to UBound($aDllArgs)
                $tData[$i-1]=DllStructCreate("char[" & StringLen($aDllArgs[$i-1])+1 & "]")
                DllStructSetData($varList,1,DllStructGetPtr($tData[$i-1]),$i)
                ;Debug Pointers
                ConsoleWrite(DllStructGetData($varList,1,$i) & @CRLF)
                DllStructSetData($tData[$i-1],1,$aDllArgs[$i-1])
            next


;Debug Strings
for $i=1 to UBound($aDllArgs)
ConsoleWrite(DllStructGetData(DllStructCreate("char[" & StringLen($aDllArgs[$i-1])+1 & "]",DllStructGetData($varList,1,$i)),1) & @CRLF)
Next

Saludos

Edited by Danyfirex
Link to comment
Share on other sites

Thanks very much for the help LarsJ and Danyfirex. Danyfirex, your solution worked perfectly... I'm still trying to get the hang of the DllStructs and how they are passed from function to function. I'm finding it tough to follow the data through the process of multiple DllStructGetData and DllStructGetPtr functions concatenated like that.

Thanks again for the explanation.

Link to comment
Share on other sites

Sorry for the up, is possible to see a working example? I have always use gswin32c executable but if i can avoid it and use only the DLL is better. Thanks

 

Certainly. So the gsdll32.dll is a little quirky because you have to initialize it, then run it, then destroy the instance when you're done.

The code by Danyfirex helps get all the args you usually pass in the command line into the AutoIt equivalent of a char** in C/C++. 

I'll walk through it for beginners so hopefully it can referenced by anyone who needs it in the future. Sorry if it's overly explanatory.

Local $aDllArgs[9] = ["gswin32c", _
                                 "-sDEVICE=pdfwrite", _
                                 "-dNOPAUSE", _
                                 "-dBATCH", _
                                 "-dSAFER", _
                                 "-dFirstPage=" & $aParseArgs[3], _
                                 "-dLastPage=" & $aParseArgs[4], _
                                 "-sOutputFile=" & $sDestName & "", _
                                 "" & $sPDFPath & ""]
   
   
   
   
   $varList = DllStructCreate("ptr[" & UBound($aDllArgs) & "]")
            $p_varList = DllStructGetPtr($varList)


         Local $tData[UBound($aDllArgs)]

            for $k= 1 to UBound($aDllArgs)
                $tData[$i-1]=DllStructCreate("char[" & StringLen($aDllArgs[$k-1])+1 & "]")
                DllStructSetData($varList,1,DllStructGetPtr($tData[$k-1]),$k)
                ;Debug Pointers
                ConsoleWrite(DllStructGetData($varList,1,$k) & @CRLF)
                DllStructSetData($tData[$k-1],1,$aDllArgs[$k-1])
            next


;Debug Strings
for $i=1 to UBound($aDllArgs)
ConsoleWrite(DllStructGetData(DllStructCreate("char[" & StringLen($aDllArgs[$i-1])+1 & "]",DllStructGetData($varList,1,$i)),1) & @CRLF)
Next

$aDllArgs is my string array for the individual arguments, $varList is the DllStruct of an array of pointers with the size of $aDllArgs. $p_varList stores the pointer to this DllStruct. $tData is created as an array of "char[]" DllStructs, each appropriately sized for the respective string in $aDllArgs. This converts the strings into char arrays for use in the C-code DLL. The corresponding $varList index ($k) then gets the pointer to this new char array, and finally $tData[$k-1] is set to the value of the string.

After all this, you can finally call the code to create and work with the instances of gsdll32.dll. The stdout of the DLL appears in the Console window when the script runs. Note: you don't have to pass the paths to the PDF input and output files in quotes - this is different than when you're using the executable. Initially, I had them in quotes and this didn't work, but you'll see in the above code in this post, I've removed the extra quotes.

Local $hDll = DllOpen(@ScriptDir & "\gsdll32.dll") ; Open the DLL

            Local $hInst
            Local $dResult = DllCall($hDll, "int", "gsapi_new_instance", "ptr*", Null, "ptr", Null) ; Create a new instance, will return a memory location to the instance in position 1 of the result array

            $hInst = $dResult[1] ; set $hInst to the pointer returned in gsapi_new_instance

            If $dResult[0] = 0 Then ; If return code was 0, proceed.
               ConsoleWrite("trying to print PDF" & @CRLF) ; Debug: checks where we are
               $dResult = DllCall($hDll, "int", "gsapi_init_with_args", "ptr", $hInst, _
                                 "int", UBound($aDllArgs), _
                                 "ptr", $p_varList) ; pass the pointer to the instance, the number of args, and the pointer to the arg array we made previously

               If @error Then
                  ; Display the error message.
                  MsgBox($MB_SYSTEMMODAL, "", "Error in DllCall (""gsapi_init_with_args""). @error = "  & @error)
                  Exit
               EndIf

               If $dResult[0] = 0 Then ; If the return code was 0, proceed
                  $dResult = DllCall($hDll, "int", "gsapi_exit", "ptr", $hInst) ; close the instance as we're now done

               EndIf

               DllCall($hDll, "none", "gsapi_delete_instance", "ptr", $hInst) ; delete the instance

            EndIf

            If @error Then
               ; Display the error message.
               MsgBox($MB_SYSTEMMODAL, "", "Can't find Ghostscript DLL (gsdll32.dll) in " & @CRLF & @ScriptDir) ; probably not needed at this point
               Exit

            EndIf

            DllClose($hDll) ; close the DLL in AutoIt
            ConsoleWrite("closed DLL" & @CRLF) ; Debug: checks where we are
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...