GPinzone Posted November 15, 2010 Share Posted November 15, 2010 I'm trying to use AutoIt to control a Primera CD/DVD Duplicator. Primera released a couple of DLLs and documentation. I'm not a C programmer, so I'm a little stuck on how to set up some of the calls. For example, their documentation lists: PTRobot_Initialize /////////////////////////// // // PTRobot_Initialize // // Description: // Function to initialize internal data structures of // the PTRobot module. // Params: // None // Notes: // Return: // PTROBOT_OK if Successful // PTROBOT_INTERNAL if an internal error occurred. // /////////////////////////// DWORD WINAPI PTRobot_Initialize(); So I created a function in AutoIT: Func PTRobot_Initialize() Local $result Local $err = @error $result = DllCall("PTRobot.dll", "int", "PTRobot_Initialize") msgbox(0, "", $result[0]) Return $result EndFunc And it seems to work. However, more complex ones like: PTRobot_EnumRobots /////////////////////////// // // PTRobot_EnumRobots // // Description: // Function to enumerate the Robots on the system. // Params: // phRobots points to an array of HANDLEs to store // the Robots found. // pdwNumRobots points to a DWORD containing the number of HANDLEs // in the phRobots array. This value is an input // and an output. The user should specify the size // (number of HANDLEs) of the phRobots array on input. // The value of the pdwNumRobots on output will be the // number of robots found. // // Notes: // Both params will be updated upon successful completion of this // command. phRobots will contain handles to robots connected to // this system. pdwNumRobots will will be updated with the number of // robots found. // Also, note that the hDrives[] array in the PTRobotInfo will not be // valid until PTRobot_EnumDrives is called. // // Return: // PTROBOT_OK if Successful // PTROBOT_INVALID_ROBOT if no robots found // PTROBOT_SEQUENCE if this command is called out of sequence // PTROBOT_INTERNAL if an internal error occurred // PTROBOT_OVERFLOW if the number of robots found is > the value in // pdwNumRobots // /////////////////////////// DWORD WINAPI PTRobot_EnumRobots(HANDLE * phRobots, DWORD * pdwNumRobots); This one has me stumped. Gerard J. Pinzonegpinzone AT yahoo.com Link to comment Share on other sites More sharing options...
JohnOne Posted November 15, 2010 Share Posted November 15, 2010 Please not that I'm no dllcall expert, and this is just an attempt at what I think it might be. $aHwnd = DllStructCreate("hwnd[10]");array struct $pHwnd = DllStructGetPtr($aHwnd);pointer to struct $Dword = DllStructCreate("dword") $pDword = DllStructGetPtr($Dword);pointer to dword Func PTRobot_Initialize(ByRef $pHwnd, ByRef $pDword) ;I think ByRef is needed when you are expecting the params to be modified Local $result Local $err = @error $result = DllCall("PTRobot.dll", "int", "PTRobot_EnumRobots", "ptr", $pHwnd, "ptr", $pDword) msgbox(0, "", $result[0]) Return $result EndFunc Like I say, dont take this as good code, its just an attempt. AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
trancexx Posted November 15, 2010 Share Posted November 15, 2010 (edited) That's just fine JohnOne (except you should set $Dword to 10). Byref is not needed; passing pointer is another word for byref. Last parameter can be ..."dword*", 10... and then collecting byref-ed as $result[2] Edited November 15, 2010 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
JohnOne Posted November 15, 2010 Share Posted November 15, 2010 thanks trancexx, I always appreciate pointers in dllcall. Sorry for the bad pun. AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
GPinzone Posted November 16, 2010 Author Share Posted November 16, 2010 Thanks to both of you for the help! Here's what I have so far: $aHwnd = DllStructCreate("hwnd[10]");array struct $pHwnd = DllStructGetPtr($aHwnd);pointer to struct $Dword = DllStructCreate("dword") DllStructSetData($Dword,1,10) $pDword = DllStructGetPtr($Dword);pointer to dword PTRobot_Initialize() PTRobot_EnumRobots($pHwnd, $pDword) Func PTRobot_Initialize() Local $result Local $err = @error $result = DllCall("PTRobot.dll", "int", "PTRobot_Initialize") msgbox(0, "", $result[0]) Return $result EndFunc Func PTRobot_EnumRobots($pHwnd, $pDword) Local $result Local $err = @error $result = DllCall("PTRobot.dll", "int", "PTRobot_EnumRobots", "ptr", $pHwnd, "ptr", $pDword) msgbox(0, "", $result[0]) Return $result EndFunc AutoIt still crashes on the PTRobot_EnumRobots function. I used DllStructSetData to set the value of the $Dword struct to 10. I'm not sure why it's giving me grief. Gerard J. Pinzonegpinzone AT yahoo.com Link to comment Share on other sites More sharing options...
trancexx Posted November 16, 2010 Share Posted November 16, 2010 (edited) Try this: Global $hPTROBOTDLL = DllOpen("PTRobot.dll") ConsoleWrite("$hPTROBOTDLL = " & $hPTROBOTDLL & @CRLF) Local $tHandles = DllStructCreate("handle[100]") ; Initialize Local $aCall = DllCall($hPTROBOTDLL, "dword", "PTRobot_Initialize") ConsoleWrite("Initialize @error = " & @error & @CRLF) ConsoleWrite("Initialize $aCall[0] = " & $aCall[0] & @CRLF) ConsoleWrite("----------------------------" & @CRLF) ; EnumRobots $aCall = DllCall($hPTROBOTDLL, "dword", "PTRobot_EnumRobots", "ptr", DllStructGetPtr($tHandles), "dword*", 100) ConsoleWrite("EnumRobots @error = " & @error & @CRLF) ConsoleWrite("EnumRobots $aCall[0] = " & $aCall[0] & @CRLF) ConsoleWrite("EnumRobots $aCall[1] = " & $aCall[1] & @CRLF) ConsoleWrite("EnumRobots $aCall[2] = " & $aCall[2] & @CRLF) edit: and post console output Edited November 16, 2010 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
GPinzone Posted November 16, 2010 Author Share Posted November 16, 2010 edit: and post console output C:\Program Files\ImgBurn>test2.exe $hPTROBOTDLL = 1 Initialize @error = 0 Initialize $aCall[0] = 0 ---------------------------- EnumRobots @error = 0 EnumRobots $aCall[0] = 0 EnumRobots $aCall[1] = 0x003B6E18 EnumRobots $aCall[2] = 1 Gerard J. Pinzonegpinzone AT yahoo.com Link to comment Share on other sites More sharing options...
trancexx Posted November 16, 2010 Share Posted November 16, 2010 (edited) So, what's the problem?Is there any problem more?edit: function says there is one Robot, handle of which is at 0x003B6E18. Edited November 16, 2010 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
GPinzone Posted November 16, 2010 Author Share Posted November 16, 2010 So, what's the problem? Is there any problem more? edit: function says there is one Robot, handle of which is at 0x003B6E18. I rewrote the program based on your example: Global $hPTROBOTDLL = DllOpen("PTRobot.dll") PTRobot_Initialize() PTRobot_EnumRobots() Func PTRobot_Initialize() Local $result Local $err = @error $result = DllCall($hPTROBOTDLL, "int", "PTRobot_Initialize") ;msgbox(0, "", $result[0]) Return $result[0] EndFunc Func PTRobot_EnumRobots() Local $result Local $err = @error Local $aHwnd = DllStructCreate("hwnd[10]") $result = DllCall($hPTROBOTDLL, "int", "PTRobot_EnumRobots", "ptr", DllStructGetPtr($aHwnd), "dword*", 10) msgbox(0, "", $result[0]) msgbox(0, "", $result[1]) msgbox(0, "", $result[2]) Return $result[0] EndFunc Now, this works without crashing. I noticed that if I just run the script without compiling it, I get 0x014F8238, but 0x003B7ED8 compiled, and both are different than yours. I'm wondering if this is the address of the pointer vs. the value? Gerard J. Pinzonegpinzone AT yahoo.com Link to comment Share on other sites More sharing options...
trancexx Posted November 16, 2010 Share Posted November 16, 2010 That's the address of the array of handles. It's irrelevant in value. Handles are read from the $tHandles ($aHwnd from your code) structure: Local $hHandle1 = DllStructGetData($tHandles, 1, 1) ;... ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
GPinzone Posted November 16, 2010 Author Share Posted November 16, 2010 That's the address of the array of handles. It's irrelevant in value. Handles are read from the $tHandles ($aHwnd from your code) structure: Local $hHandle1 = DllStructGetData($tHandles, 1, 1) ;... Ah! So the address of the device I get from the array, but the number of devices are from the return value. I verified that it works both ways since the value is now consistent. Thank you! Gerard J. Pinzonegpinzone AT yahoo.com Link to comment Share on other sites More sharing options...
GPinzone Posted November 16, 2010 Author Share Posted November 16, 2010 I believe I'm getting the hang of this now. I've used AutoIt before, but I never got in so deep that ever tried interacting with DLLs. Here's my update test program: expandcollapse popupGlobal $hPTROBOTDLL = DllOpen("PTRobot.dll") Global $RobotAddress PTRobot_Initialize() $RobotAddress = PTRobot_EnumRobots() msgbox(0, "", $RobotAddress) PTRobot_GetRobotStatus() Func PTRobot_Initialize() Local $result Local $err = @error $result = DllCall($hPTROBOTDLL, "int", "PTRobot_Initialize") if $result[0] Then MsgBox(0,"DllCall Error","DllCall Failed: PTRobot_Initialize") exit EndIf EndFunc Func PTRobot_EnumRobots() Local $result Local $err = @error Local $hRobots = DllStructCreate("hwnd[10]") Local $dwNumRobots $result = DllCall($hPTROBOTDLL, "int", "PTRobot_EnumRobots", "ptr", DllStructGetPtr($hRobots), "dword*", 10) if $result[0] Then MsgBox(0,"DllCall Error","DllCall Failed: PTRobot_EnumRobots") exit EndIf Local $dwNumRobots = $result[2] ;msgbox(0, "", DllStructGetData($hRobots, 1, 1)) ;msgbox(0, "", $dwNumRobots) Return DllStructGetData($hRobots, 1, 1) EndFunc Func PTRobot_GetRobotStatus() Local $result Local $err = @error Local $hRobot = DllStructCreate("hwnd") DllStructSetData($hRobot,1,$RobotAddress) Local $dRobotStatus = DllStructCreate("dword dwSystemState;dword dwSystemError;dword dwCurrColorSpits;dword dwCurrBlackSpits;dword dwFullColorSpits;dword dwFullBlackSpits") $result = DllCall($hPTROBOTDLL, "int", "PTRobot_GetRobotStatus", "ptr", DllStructGetPtr($hRobot), "ptr", DllStructGetPtr($dRobotStatus)) msgbox(0, "Status", $result[0]) msgbox(0, "", "System State: " & DllStructGetData($dRobotStatus, "dwSystemState") & @CRLF & _ "System Error: " & DllStructGetData($dRobotStatus, "dwSystemError")) Return $result[0] EndFunc Thankfully, it doesn't crash anymore. However, the new function "PTRobot_GetRobotStatus" is returning a value of 502, which is PTROBOT_INVALID_ROBOT. Is it possible something got messed up when I passed the address around between variables? Here's the documentation for the PTRobot_GetRobotStatus function for the DLL: 2.2.3 PTRobot_GetRobotStatus /////////////////////////// // // PTRobot_GetRobotStatus // // Description: // Function to get the current status for a particular // robot. // Notes: Do NOT call in too tight of a loop (e.g. do not call more often // than every 500ms or so). // Params: // hRobot Handle to the robot (from EnumRobots) // pRobotStatus points to a PTRobotStatus structure. // Notes: // Return: // PTROBOT_OK if Successful // PTROBOT_SEQUENCE if this command is called out of sequence // PTROBOT_INTERNAL if an internal error occurred // PTROBOT_INVALID_ROBOT if the robot handle is invalid // /////////////////////////// DWORD WINAPI PTRobot_GetRobotStatus(HANDLE hRobot, PTRobotStatus *pRobotStatus); Gerard J. Pinzonegpinzone AT yahoo.com Link to comment Share on other sites More sharing options...
trancexx Posted November 16, 2010 Share Posted November 16, 2010 First param for PTRobot_GetRobotStatus function is Robot handle. There is no need to make it more complex than it is. Do you understand what I'm saying? ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
GPinzone Posted November 16, 2010 Author Share Posted November 16, 2010 (edited) First param for PTRobot_GetRobotStatus function is Robot handle. There is no need to make it more complex than it is.Do you understand what I'm saying?Oh for cry-not-loud. I was so used to passing a pointer, I didn't even catch that all I needed was to send it the handle. Sorry. Edited November 16, 2010 by CPinzone Gerard J. Pinzonegpinzone AT yahoo.com Link to comment Share on other sites More sharing options...
GPinzone Posted November 16, 2010 Author Share Posted November 16, 2010 Well, I've actually gotten really far. I've been able to control the robot to pick up a disc from a bin and put it into the printer. The problem is sending the filename to print. 2.3.7 PTRobot_PrintFile /////////////////////////// // // PTRobot_PrintFile // // Description: // Function to print a Surething image (.STD), raster image (.JPG, .BMP, .TIF, // etc.), or .PRN file to the printer. // Params: // hRobot Handle to the robot (from EnumRobots) // tszFile File to print (.STD, .PRN, .JPG, .BMP) // dwPrintIndex Print index for multiple print jobs. // Notes: // The dwPrintIndex is used when printing an .STD file with merge fields. This // value represents which merge record to use for this print. // Return: // PTROBOT_OK if Successful // PTROBOT_SEQUENCE if this command is called out of sequence // PTROBOT_INTERNAL if an internal error occurred // PTROBOT_INVALID_ROBOT if the robot handle is invalid // PTROBOT_NO_PRINTER if the robot doesn't have a printer // PTROBOT_PRN_INVALID if the prn file is not valid for the printer // PTROBOT_PRINTFILE_NOT_FOUND if the file doesn't exist // PTROBOT_PRINTAPP_NOT_INSTALLED if the required print application is not // installed. // /////////////////////////// DWORD WINAPI PTRobot_PrintFile(HANDLE hRobot, TCHAR * tszFile, DWORD dwPrintIndex); How do I use DllCall to send a string? The DLLCall documentation doesn't even list "char" as a valid datatype. (I had another function that needed an array of chars inside of a struct, but the only thing passed in DllCall was a pointer to that struct.) I tried: $result = DllCall($hPTROBOTDLL, "int", "PTRobot_PrintFile", "hwnd", $RobotAddress, "char*", "C:\filename.prn", "dword", 0) but that didn't work. Gerard J. Pinzonegpinzone AT yahoo.com Link to comment Share on other sites More sharing options...
PsaltyDS Posted November 16, 2010 Share Posted November 16, 2010 What made you think the string was byRef? Maybe try "str" vice "char*". Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
GPinzone Posted November 16, 2010 Author Share Posted November 16, 2010 What made you think the string was byRef? Maybe try "str" vice "char*".I tried str and it worked. I didn't think it would since it looks like a different datatype. Gerard J. Pinzonegpinzone AT yahoo.com Link to comment Share on other sites More sharing options...
PsaltyDS Posted November 17, 2010 Share Posted November 17, 2010 Does that mean you've got the whole thing working now? That would be cool. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
GPinzone Posted November 17, 2010 Author Share Posted November 17, 2010 Does that mean you've got the whole thing working now? That would be cool.Yes. It's working great. I've been working on the error handling today. I'd like to release the code as a beta for people to use (assuming they have access to the DLL files from Primera). It certainly isn't polished as much as I'd like, but it works really well and handles errors like discs in the wrong place or the cover open. I didn't write it with multiple robots/burners in mind since I don't have that kind of configuration and can't test it. I use IMGBurn as the burning engine via command line. I know IMGBurn can work with the robot directly, but it wont print labels and doesn't handle certain error conditions.What's a good place to submit it? Is SourceForge a good place? Gerard J. Pinzonegpinzone AT yahoo.com Link to comment Share on other sites More sharing options...
PsaltyDS Posted November 17, 2010 Share Posted November 17, 2010 I think you have enough posts now to put it in the Example Scripts forum. Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now