Yorgo Posted February 22, 2018 Share Posted February 22, 2018 hello, as far as I understood the documentation, "DllCall()" returns an array (32-/64-bit or variable sized?) values, the first @ index 0 being the actual return value of the called function!? but: - what if that function does not only return any scalar value, but a whole struct?? how do I specify the DllCall wrapper for any such function?? Example: <C-code> struct ftdi_version_info version; version = ftdi_get_library_version(); printf("Initialized libftdi %s (major: %d, minor: %d, micro: %d, snapshot ver: %s)\n", version.version_str, version.major, version.minor, version.micro, version.snapshot_str); <Header> struct ftdi_version_info { int major; int minor; int micro; const char *version_str; const char *snapshot_str; }; Link to comment Share on other sites More sharing options...
Danyfirex Posted February 22, 2018 Share Posted February 22, 2018 Hello. You need to do something like this. Global Const $sTag_ftdi_version_info="int major;int minor;int micro;ptr pversion_str;ptr psnapshot_str" Local $aRet=DllCall("somedll.dll","ptr","ftdi_get_library_version") Local $t_ftdi_version_info=DllStructCreate($sTag_ftdi_version_info,$aRet[0]) Local $tversion_str=DllStructCreate("char Data[256]",DllStructGetData($t_ftdi_version_info,"pversion_str")) ConsoleWrite(DllStructGetData($t_ftdi_version_info,"major") & @CRLF) ConsoleWrite(DllStructGetData($tversion_str,1) & @CRLF) Saludos Danysys.com AutoIt... UDFs: VirusTotal API 2.0 UDF - libZPlay UDF - Apps: Guitar Tab Tester - VirusTotal Hash Checker Examples: Text-to-Speech ISpVoice Interface - Get installed applications - Enable/Disable Network connection PrintHookProc - WINTRUST - Mute Microphone Level - Get Connected NetWorks - Create NetWork Connection ShortCut Link to comment Share on other sites More sharing options...
Yorgo Posted February 23, 2018 Author Share Posted February 23, 2018 nope, doesn't work... this 'ftdi_get_library_version()' does not return a pointer to the version structure, but the structure itself - you may have missed that... should be something like DllCall("libftdi1.dll", "struct", "ftdi_get_library_version") then - but this together with the rest of your code does not give valid output Link to comment Share on other sites More sharing options...
jchd Posted February 23, 2018 Share Posted February 23, 2018 Weird. This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe hereRegExp tutorial: enough to get startedPCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta. SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt) Link to comment Share on other sites More sharing options...
RTFC Posted February 23, 2018 Share Posted February 23, 2018 @Yorgo: You are confusing a library (.lib) with a dll. If the ftdi library is linked with a compiled object (say, in C# or C++), then the version struct is returned directly. However, from AutoIt you need to call the D2XX dll, as detailed here (Google is your friend): http://www.ftdichip.com/Support/Documents/ProgramGuides/D2XX_Programmer's_Guide(FT_000071).pdf and when calling that dll (function FT_GetLibraryVersion I think), you need to supply a pointer (LPDWORD) to your own struct, which the dll call can then fill with the version data. @Danyfirex is totally correct. My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O Link to comment Share on other sites More sharing options...
jguinch Posted February 23, 2018 Share Posted February 23, 2018 I'm not very familiar with DllCall and structures, but in the help file I see that the valid types list contains STRUCT. Can it be used as a return type ? Local $aRet=DllCall("somedll.dll","struct","ftdi_get_library_version") ConsoleWrite( "ver.major : " & DllStructGetData($aRet[0], 1) ) Spoiler Network configuration UDF, _DirGetSizeByExtension, _UninstallList Firefox ConfigurationArray multi-dimensions, Printer Management UDF Link to comment Share on other sites More sharing options...
RTFC Posted February 24, 2018 Share Posted February 24, 2018 (edited) @jguinch: I guess it's possible in theory, but it's a really bad idea (both in terms of performance and maintainability), and I know of only one example on the forum where something remotely like it was partially successful (and only because the returned item turned out not to be a struct after all). But I wouldn't expect AutoIt to allocate more than 8 bytes (64K for STR??) for DllCallresult[0], so anything over the maximum would likely be clipped (never tried it though). In the OP's context it's a moot point, because the posted snippet uses a (compiled, inapplicable) library function that works differently from the dll equivalent that can be called from AutoIt. Edited February 24, 2018 by RTFC My Contributions and Wrappers Spoiler BitMaskSudokuSolver BuildPartitionTable CodeCrypter CodeScanner DigitalDisplay Eigen4AutoIt FAT Suite HighMem MetaCodeFileLibrary OSgrid Pool RdRand SecondDesktop SimulatedAnnealing Xbase I/O Link to comment Share on other sites More sharing options...
Danyfirex Posted February 24, 2018 Share Posted February 24, 2018 It would be easier if you share the library and documentation you're using... Saludos Danysys.com AutoIt... UDFs: VirusTotal API 2.0 UDF - libZPlay UDF - Apps: Guitar Tab Tester - VirusTotal Hash Checker Examples: Text-to-Speech ISpVoice Interface - Get installed applications - Enable/Disable Network connection PrintHookProc - WINTRUST - Mute Microphone Level - Get Connected NetWorks - Create NetWork Connection ShortCut Link to comment Share on other sites More sharing options...
Yorgo Posted February 26, 2018 Author Share Posted February 26, 2018 (edited) I'm not confusing anything, it's taken directly from the DLL documentation - not LIB documentation, example code - see here:https://www.intra2net.com/en/developer/libftdi/documentation/ all of those "ftdi_xyz()" functions are DLL exports, see attachement more details: - the piece of hardware is a simple Relais-Box, 8 ports that can be switched to either A or B, connected to the PC via parallel port - this box worked perfectly in my old PC, but: I just got a new PC that does not have any parallel port anymore! - thus this switch-box is connected via an USB-to-parallel adapter now which is controlled via libftdi1 - we have this kind of adapter operational with libftdi1 and a self-made C-sharp programm for our company's Testsuite - running this whole Testsuite only to have a simple switch change position is overlloaded, that's where AutoIt comes into play - so far without success... what does work: - when I disconnect the USB-Cable or change the Vendor-/Product-Id in "ftdi_usb_open()" to something not matching this adatapter, the call to ftdi_usb_open() fails - when connected and the correct Ids are used, the call succeeds -> so it does see the adapter already but: I cannot read the current parallel port values nor change them --- re-coding this example concerning ftdi_get_library_version() was just to verifiy that talking to the library works - having this function returning the whole struct and not given a pointer to copy the information into is really bad, I totally agree nothing I can do about it -- but it still is valid C code... Edited February 26, 2018 by Yorgo more info Link to comment Share on other sites More sharing options...
Tekk Posted February 26, 2018 Share Posted February 26, 2018 A function cannot return a structure, not with conventional calling conventions, however they may return them by reference. It's just not how x86 CPU's are designed work at low level, most return values are given back in CPU registers where a structure generally will not fit. Just because the source code looks as if it does, that is not what the compiler is really doing. ftdi_get_library_version accepts one parameter; a pointer to a ftdi_version_info structure. It also uses cdecl calling convention. I know this because I loaded the library into a debugger. The following example does work, I have tested it. I chose to load the structure into an array for ease of display. #include <Array.au3> Global $g_hDll = DllOpen("libftdi1.dll") If $g_hDll < 0 Then MsgBox(0x40000, "Error!", "Failed to load library!") Else Global $g_aVersion = ftdi_get_library_version() _ArrayDisplay($g_aVersion) EndIf Func ftdi_get_library_version() Local $ftdi_version_info = DllStructCreate("INT major;INT minor;INT micro;PTR version_str;PTR snapshot_str") DllCall($g_hDll, "NONE:cdecl", "ftdi_get_library_version", "STRUCT*", $ftdi_version_info) Local $aReturn[5][2] = [["major"], ["minor"], ["micro"], ["version_str"], ["snapshot_str"]] $aReturn[0][1] = $ftdi_version_info.major $aReturn[1][1] = $ftdi_version_info.minor $aReturn[2][1] = $ftdi_version_info.micro $aReturn[3][1] = DllStructGetData(DllStructCreate("CHAR[255]", $ftdi_version_info.version_str ), 1) $aReturn[4][1] = DllStructGetData(DllStructCreate("CHAR[255]", $ftdi_version_info.snapshot_str), 1) Return $aReturn EndFunc Link to comment Share on other sites More sharing options...
Yorgo Posted February 26, 2018 Author Share Posted February 26, 2018 well, I wasn't referring to what the assembler does but purely from C-language point-of-view: here it absolutely is legal and does work to return a whole structure - the assembler underneath actually inserts references to memcpy() when compiling that piece of code to copy the "return" value into the callers scope (but all the nasty details about that are way off-topic here) coming to your example code: the api-header looks differently to what you are using - how would anyone not knowing how to debug such low-level DLL calls come to the idea to just pass a pointer and completely ignore the given interface?? I will try it out and post any results as soon as I got 'em... Link to comment Share on other sites More sharing options...
Yorgo Posted February 26, 2018 Author Share Posted February 26, 2018 (edited) <results> yes, strange enough , it does work as in your example, weird tho... - library reports to be "v1.0.6-gafb9082" for me, hmm... seems there is no Windows build for the newest version available anyway, could you PLEASE also look up "ftdi_read_pins", "ftdi_read_data" and "ftdi_write_data" - with respect to how to call those functions from AutoIt?? - those are the functions to read the current Parallel-Port settings and to change them; that's all I need here I updated your example as follows: expandcollapse popup#include <Array.au3> Global $g_hDll = DllOpen("libftdi1.dll") Global $g_pContext = 0 If $g_hDll < 0 Then MsgBox(0x40000, "Error!", "Failed to load library!") Else Global $g_aVersion = ftdi_get_library_version() Local $types = DllStructCreate("BYTE byte_val;INT int_val;") Local $ptrByte = DllStructGetPtr($types, "byte_val") Local $ptrInt = DllStructGetPtr($types, "int_val") $ret = DllCall($g_hDll, 'PTR:cdecl', 'ftdi_new') $g_pContext = $ret[0] MsgBox(0, "Debug", "ftdi_new=" & $g_pContext & "; error=" & @error) $ret = DllCall($g_hDll, "INT:cdecl", "ftdi_init", "PTR", $g_pContext) MsgBox(0, "Debug", "ftdi_init=" & $ret[0] & "; error=" & @error) _ArrayDisplay($g_aVersion) $ret = DllCall($g_hDll, "INT:cdecl", "ftdi_usb_open", "PTR", $g_pContext, "INT", 0x0403, "INT", 0x5121) MsgBox(0, "Debug", "ftdi_usb_open=" & $ret[0] & "; error=" & @error) $types.int_val = -1 $ret = DllCall($g_hDll, "INT:cdecl", "ftdi_read_chipid", "PTR", $g_pContext, "INT_PTR", $ptrInt) MsgBox(0, "Debug", "ftdi_read_chipid=" & $ret[0] & ",id=" & StringFormat("%X", $types.int_val) & "; error=" & @error) $ret = DllCall($g_hDll, "INT:cdecl", "ftdi_set_bitmode", "PTR", $g_pContext, "BYTE", 0xff, "BYTE", 4) MsgBox(0, "Debug", "ftdi_set_bitmode=" & $ret[0] & "; error=" & @error) $types.byte_val = -1 $ret = DllCall($g_hDll, "INT:cdecl", "ftdi_read_pins", "PTR", $g_pContext, "BYTE_PTR", $ptrByte) _ArrayDisplay($ret) MsgBox(0, "Debug", "ftdi_read_pins [error=" & @error & "] pins=" & $types.byte_val) EndIf Func ftdi_get_library_version() Local $ftdi_version_info = DllStructCreate("INT major;INT minor;INT micro;PTR version_str;PTR snapshot_str") DllCall($g_hDll, "NONE:cdecl", "ftdi_get_library_version", "STRUCT*", $ftdi_version_info) Local $aReturn[5][2] = [["major"], ["minor"], ["micro"], ["version_str"], ["snapshot_str"]] $aReturn[0][1] = $ftdi_version_info.major $aReturn[1][1] = $ftdi_version_info.minor $aReturn[2][1] = $ftdi_version_info.micro $aReturn[3][1] = DllStructGetData(DllStructCreate("CHAR[255]", $ftdi_version_info.version_str ), 1) $aReturn[4][1] = DllStructGetData(DllStructCreate("CHAR[255]", $ftdi_version_info.snapshot_str), 1) Return $aReturn EndFunc Everything up to where "ftdi_read_pins" is called is reasonable; i.e. I do get a Chip-Id different from 0xFFFFFFFF when the adapter is connected - and equal to 0xFFFFFFFF when it is not, together with a return value indicating that there was an error (-3 here) BUT: the call to "ftdi_read_pins" acts weird: - the return value from DllCall is not an array as it used to be anymore, but just '0' - @error is '-1' - which is according to the documentation "unable to use the DLL file" why can't I all of the sudden not use the Dll anymore, and why does DllCall not return an array anymore? ---- ah, the array only is returned in case of no-errors, is it not? but still, what does "unable to use the DLL file" *mean*? I successfully used that exact DLL file multiple times before... Edited February 26, 2018 by Yorgo Link to comment Share on other sites More sharing options...
LarsJ Posted February 26, 2018 Share Posted February 26, 2018 What does "BYTE_PTR" mean? Does DllCall know about that? Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
Bilgus Posted February 26, 2018 Share Posted February 26, 2018 I agree with LarsJ I think your hangeup is probably that BYTE_PTR You might already have found these but http://libftdi.sourcearchive.com/documentation/0.18-1build1/group__libftdi_gb823dd90f2359612b1546ef0ceebdc0e.html and https://github.com/legege/libftdi/blob/master/examples/bitbang_cbus.c Should give Us (or You) a little more context from the documentation it looks like a return of 0 from read_pins = OK Link to comment Share on other sites More sharing options...
Yorgo Posted February 27, 2018 Author Share Posted February 27, 2018 (edited) thx for that hint - I "thought" there was something like a BYTE_PTR since there are INT_PTR and LONG_PTR existing; my bad BUT: why does "INT_PTR" acts different from "INT*" - must that not be the same? (well, in C it is at last) - e.g. if I replace in my code above that "INT_PTR" where i read the Chip-Id with an "INT*" I cannot read the Chip-Id anymore as for reading the pins: "BYTE*" does not generate any weird DllCall() behavior anymore, but I cannot read the pins like this! is it safe to just use a generic "PTR" here?? <update> anyway - when using a simple "PTR" I now not only can read the current pins but also can change them!!!! you people rock, thanx! Edited February 27, 2018 by Yorgo Link to comment Share on other sites More sharing options...
Andreik Posted February 27, 2018 Share Posted February 27, 2018 * in AutoIt is used when you pass a parameter by reference, so INT* means that you pass and integer data type by reference and INT_PTR means you pass an integer with respect to system architecture to hold a pointer. When the words fail... music speaks. Link to comment Share on other sites More sharing options...
Yorgo Posted February 27, 2018 Author Share Posted February 27, 2018 hmmm... that is the same, is it not? if a variable is passed by reference, it does mean the called function writes its content into the very same memory address that was assigned for this variable by the caller of that Dll-Funtion, i.e. once the Dll-function returned, the caller does (should) see the updated value as written into the variable by the Dll function! - this only works when using "INT_PTR" or the generic "PTR", but not for "INT *" to me this looks like a bug... Link to comment Share on other sites More sharing options...
LarsJ Posted February 27, 2018 Share Posted February 27, 2018 This has nothing to do with bugs. "INT_PTR" and "INT*" does not work in the same way. You've already seen how "INT_PTR" works very well with the storage you've created in the structure. When you use "INT*" the storage for the integer is created internally by the DllCall function and the value of the integer (not the pointer) is returned in $ret[2]: $ret = DllCall($g_hDll, "INT:cdecl", "ftdi_read_chipid", "PTR", $g_pContext, "INT*", 0) ; 0 is just a placeholder for the output parameter Local $iChipid = $ret[2] You can also do it this way: Local $iChipid $ret = DllCall($g_hDll, "INT:cdecl", "ftdi_read_chipid", "PTR", $g_pContext, "INT*", $iChipid) ; $iChipid is just a placeholder for the output parameter $iChipid = $ret[2] In your original code you'll see that $ret[2] = $ptrInt. $ret = DllCall($g_hDll, "INT:cdecl", "ftdi_read_chipid", "PTR", $g_pContext, "INT_PTR", $ptrInt) Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions 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