Sign in to follow this  
Followers 0
rodent1

How do I get a pointer to an array of pointers to buffers

11 posts in this topic

#1 ·  Posted (edited)

Hi,

I need to call a c++ dll and pass to it a pointer to an array of pointers to buffers. The DLL will then fill the buffers with GUID strings. But it seems that my array pointer is not valid.

This is the latest of what I have tried:

Dim $sJobIDs[100], $structJobIdsPtrs[100], $StructJobID, $JobIDsPtr
;
for $i=0 to UBound($sJobIDs) - 1
$sJobIDs[$i]="                                  " ;enough space for a GUID
$StructJobID = ByteStructFromString($sJobIDs[$i]) ;turn this string into a char array in a C++ structure
$structJobIdsPtrs[$i] = DllStructGetPtr($StructJobID) ;store the pointer to the char array structure
Next
; get a pointer to the first item in the array of pointers
$JobIDsPtr = DllStructGetPtr(DllStructCreate("ptr", $structJobIdsPtrs[0]))
msgbox(0,"","pointer value = " & $JobIDsPtr)
Func ByteStructFromString ( byref $TheString )
Dim $struct = DllStructCreate ( "byte[" & StringLen ( $TheString ) & "]" )
DllStructSetData ( $struct, 1, StringToBinary ( $TheString ) )
Return $struct
EndFunc

But when I display the value of $JobIDsPtr, I get a zero. What am I doing wrong?

Thanks

Edited by rodent1

Share this post


Link to post
Share on other sites



But on my win 7 32 bit, I get the value of a pointer in the msgbox.

as do I on my Win7 64bit machine (running autoit as 32 bit)

kylomas


Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post


Link to post
Share on other sites

on this line

$structJobIdsPtrs[$i] = DllStructGetPtr($StructJobID) ;store the pointer to the char array structure
he is getting the pointer of a dllstruct, but $StructJobID isn't a dllstruct. Am I wrong?

Share this post


Link to post
Share on other sites

@LaCastiglione,

I'm not sure that it is any more complicated than

Local $structjobidsptrs = DllStructCreate("ptr[100]")
Local $ptr_jobIDptrs    = DllStructGetPtr($structjobidsptrs)

kylomas


Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

@rodent1

That's not how you create an array of something. As the helpfile tell you on the page for DllStructCreate();

Create arrays by adding '' after the data type: DllStructCreate("int;char[128]")

now the second element is an array of 128 chars. Couple that knowledge with DllStructGetPtr() and you're finished. Actually, looking at ByteStructFromString() it seems you know all this.

on this line

$structJobIdsPtrs[$i] = DllStructGetPtr($StructJobID) ;store the pointer to the char array structure
he is getting the pointer of a dllstruct, but $StructJobID isn't a dllstruct. Am I wrong?

And what do you think DllStructCreate() returns? :)

EDit:

@kylomas

Probably something like that.

@JohnOne

I'm not sure if you don't know how DllStructCreate() works or is trying to make a clever remark that 100 is too much/not the right amount.

Edited by AdmiralAlkex

Share this post


Link to post
Share on other sites

I like the simplicity of Kylomas's solution,

Local $structjobidsptrs = DllStructCreate("ptr[100]")
Local $ptr_jobIDptrs    = DllStructGetPtr($structjobidsptrs)

but it does not allocate the memory needed for the API to fill the data. I tried it as a long shot anyway. The API did not fill it.

I have a API description to go by:

Description :

Retrieves a list of job IDs of the jobs currently on the server.

The job_list array needs to be created and populated with pointers to buffers for the job IDs before calling this function.

the maximum size of each job ID is 256

C prototype :

HarmResult JOBM_getJobList(

HarmSessionHandle *session,

int32 skip,

int32 max,

char **job_list /* [] */,

int32 *num_jobs,

HarmNBTicket *nbticket)

so I start by creating the buffers, then put them in cstructs, get a pointer to those, populate my array of pointers, put the array of pointers into a cstruct, but then I fail to get a pointer to it

dim $struct_JobID ; stuct to hold GUIDs returned by API call
Dim $ptr_JobIds[100] ; struct containing an array of pointers to job ID string buffers
 for $i=0 to UBound($ptr_JobIds) - 1
  $struct_JobID = DllStructCreate("char[256]"); allocate memory for a 256 byte string struct
  $ptr_JobIds[$i] = DllStructGetPtr($struct_JobID); store a pointer to the job ID struct
 Next
 ; put the array $ptr_JobIds into a structure
 Dim $struct_ptr_JobIds = DllStructCreate("ptr", $ptr_JobIds)
 ; get a pointer to $struct_ptr_JobIds
 Dim $ptr_struct_ptr_JobIds = DllStructGetPtr($struct_ptr_JobIds)
 MsgBox(0,'Debug line ' & @ScriptLineNumber,'$ptr_struct_ptr_JobIds: I get a 0 value here!' & @lf & $ptr_struct_ptr_JobIds)
 ; put that pointer into a pointer struct
 Dim $struct_ptr_struct_ptr_JobIds = DllStructCreate("ptr", $ptr_struct_ptr_JobIds)
 Dim $ptr_ptr_JobIdPtrs = DllStructGetPtr($struct_ptr_struct_ptr_JobIds)

The command DllStructGetPtr($struct_ptr_JobIds) returns a 0.

I am a newbie in this area and appreciate all the help!

Share this post


Link to post
Share on other sites

autoit arrays != c arrays. you need to create a dllstruct for 100 ptrs, and fill each with a ptr to a created dllstruct, like this:

const $MAX_BUF = 0xFF
$job_list = dllstructcreate("ptr[100]") ; char ** job_list = (char**) malloc(100 * sizeof(char*));
const $p_job_list = dllstructgetptr($job_list)

for $i = 1 to 100 ; for(int i = 0; i < 100; ++i) {
      dllstructsetdata($job_list, _ ;job_list[i] =
                $i, _
                dllstructgetptr( _
                dllstructcreate("char[" & $MAX_BUF & "]"))) ; (char*) malloc(MAX_BUF * sizeof(char));
next; }

consolewrite("job_list is located at: " & $p_job_list & @CRLF)

Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG

Share this post


Link to post
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
Sign in to follow this  
Followers 0

  • Similar Content

    • luckyluke
      By luckyluke
      Hello,
      Im trying to read the output from CMD using Dllcall, here is my code:
      #include <WinAPI.au3> #include <array.au3> Global Const $STD_OUTPUT_HANDLE = -11 Global Const $_CONSOLE_SCREEN_BUFFER_INFO = _ "struct;int dwSizeX;" & _ "short dwSizeY;" & _ "short dwCursorPositionX;" & _ "short dwCursorPositionY;" & _ "short wAttributes;" & _ "short Left;" & _ "short Top;" & _ "short Right;" & _ "short Bottom;" & _ "short dwMaximumWindowSizeX;" & _ "short dwMaximumWindowSizeY;endstruct" $pCmd = Run( "cmd.exe" ) Sleep(1000) $hCmd = WinGetHandle("") ConsoleWrite('handle:' & $hCmd & @CRLF) $aRet = DllCall("kernel32.dll", "int", "AttachConsole", "dword", $pCmd) ;_ArrayDisplay($aRet) If $aRet[0] <> 0 Then $vHandle_data='' $vHandle='' $vHandle_data = DllStructCreate($_CONSOLE_SCREEN_BUFFER_INFO) ; Screen Buffer structure $aRet1 = DllCall("kernel32.dll", "hwnd", "GetStdHandle", "dword", $STD_OUTPUT_HANDLE) if not @error Then $vHandle = $aRet1[0] $aRet = DllCall("kernel32.dll", "int", "GetConsoleScreenBufferInfo", "hwnd", $vHandle, _ "ptr", $vHandle_data) MsgBox(0, '1',DllStructGetData($vHandle_data, 'dwSizeX') & _WinAPI_GetLastErrorMessage()) EndIf It did not work, i got the message 'The handle is invalid'. Please help?
      Thank you in advance!
    • MazeM
      By MazeM
      Hi
      here's another UDF for the serial port. It is very similar to CommAPI using kernel32.dll, but all code is packed into a single file without any dependencies, not even using WinAPI.au3. It differs from existing UDF that it doesn't allow a timeout when reading, instead it always returns immediately, either with the requested amount ob bytes read or with a failure status. And of course there is a function provided to query the amount of available bytes in the receive buffer. The reason behind this design decision: You can do 1000 other things in the main loop while checking from time to time if enough data bytes arrived. There's no point to block the program waiting for the serial port.
      It is currently a work-in-progress, as I didn't test all functions yet. The code was developed and tested on Windows 7 64 bit.  The ComUDF-Tests.au3 shows some tests and basic usage of the UDF. Maybe there's no reason to use this UDF, given the existence of the others UDFs, but I did it to get to know DllCall better - I use structs no only to pass but also to get data back (I don't use the array returned by DllCall to read that data, unless required). You're welcome to test it on older and newer Windows versions.
      Here's a list of the implemented functions:
      ; _ComListPorts ; _ComOpenPort ; _ComSetTimeouts ; _ComClosePort ; ; _ComSetBreak ; _ComClearBreak ; _ComGetInputcount ; _ComGetOutputcount ; _ComClearOutputBuffer ; _ComClearInputBuffer ; ; _ComSendByte ; _ComReadByte ; _ComSendBinary ; _ComReadBinary ; ; _ComSendChar ; _ComReadChar ; _ComSendCharArray ; _ComReadCharArray ; _ComSendString ; _ComReadString ; ; __ComClearCommError ; __PurgeComm Maze
       
      ComUDF.au3
      ComUDF-Tests.au3
    • astrionn
      By astrionn
      So I had this Idea of creating a tooltip which shows me my ping.
      That itself was made quickly and I thought too add a couple features.
      I want the tooltip background to be a different color depending on the ping. (good ping is green, medium ping is yellow,...)
      So how do I color in a tooltip? google brought me to this: 
       
      where in the comments I found this:
      $s = "LOW" ToolTip($s, 0, 0, "Battery Information");, $icon) $H_TOOLTIP1 = WinGetHandle($s) DllCall("UxTheme.dll", "int", "SetWindowTheme", "hwnd", $H_TOOLTIP1, "wstr", "", "wstr", "") DllCall("user32.dll", "int", "SendMessage", "hwnd", $H_TOOLTIP1, "int", 1043, "int", 2552550, "int", 0) Sleep(1000) Which I then used in my code with different color codes... Trial and Error brought me these that I wanted to use:
       
      The Problem is if I loop through my code it only sets the color for the 1st loop and then sticks to it.
      The real problem is tho that I don't exactly understand the dllcalls... And I guess that's why it isn't working
      So if someone would be so awesome to explain to me how they work, or at least can give me a list of these parameters then I would really appreciate that and learn something new
      Obviously a solution to my problem is awesome aswell ^^
      I run this under Windows 8.1
      There is my code in a paste.
      https://pastebin.com/q525f7mS
    • Leo1906
      By Leo1906
      Hello Guys,
      once aggain I need your help on a DLL Topic
      I need to pass arguments to my function via a structure, because I am limited to only one argument that can be passed.
      But I don't think that thats so important.
      So here's my approach:
      C++ Code (just the important part):
      extern "C" { struct ParamStruct { const char* test1; const char* test2; const char* test3; int size; }; int testFunc(struct ParamStruct * params) { return params->size; } } And thats how I try to call the function using Autoit:
      Local $struct = "struct;char shapefile[128];char output[128];char filename[128];int size;endstruct" Local $tTest = DllStructCreate($struct) DllStructSetData($tTest, "test1", "Bla") DllStructSetData($tTest, "test2", "BlaBla") DllStructSetData($tTest, "test3", "BlaBlaBla") DllStructSetData($tTest, "size", 40) $dll = DLLOpen("myDLL.dll") $ret = DllCall($dll, "int:cdecl", "testFunc", "STRUCT*", DllStructGetPtr($tTest)) MsgBox(0, 0, $ret[0]) DllClose($dll) Just for testing I want the function to just return the integer value in the struct.
      But this aint working. I tested many things, but still I'm not able to get it running. I even don't know if the mistakes are in the C++ code or the Autoit code or both .. I'm not that skilled at C++ and also not that skilled at Autoit DLLCalls :-/
      I would really appreciate some help!
      Kind regards,
      leo
    • MagicSpark
      By MagicSpark
      Hello,
      can someone help me out with some DllCall in AU3.
      The relevant source of function and struct definition are as follows (in slightly modified form):
      typedef struct {     char    *host;     char    *key;     char    *value; } test_sender_value_t; /******************************************************************************  * Parameters: address   - [IN] server address                                *  *             port      - [IN] server port                                   *  *             source    - [IN] source IP, optional - can be NULL             *  *             values    - [IN] array of values to send                       *  *             count     - [IN] number of items in values array               *  *             result    - [OUT] the server response/error message, optional  *  *                                                                            *  * Return value: 0 - the values were sent successfully, result contains       *  *                         server response                                    *  *               -1 - an error occurred, result contains error message        *  *                                                                            *  ******************************************************************************/ TEST_API int test_sender_send_values(const char *address, unsigned short port, const char *source, const test_sender_value_t *values, int count, char **result);
      In AutoIt I use the following code to build the struct and call the dll:
      Global $struct = DllStructCreate("ptr ptrtostring1;ptr ptrtostring2;ptr ptrtostring3;") Global $string1 = DllStructCreate("char host[255];") DllStructSetData($string1, "host", "Test_Client") DllStructSetData($struct, "ptrtostring1", DllStructGetPtr($string1)) Global $string2 = DllStructCreate("char key[255];") DllStructSetData($string2, "key", "clientver") DllStructSetData($struct, "ptrtostring2", DllStructGetPtr($string2)) Global $string3 = DllStructCreate("char value[255];") DllStructSetData($string3, "value", "123456") DllStructSetData($struct, "ptrtostring3", DllStructGetPtr($string3)) Global $aCall = DllCall("C:\temp\test.dll", "int", "test_sender_send_values", _     "str", "192.168.1.2", _     "int", 80, _     "str", "192.168.1.3", _     "ptr", DllStructGetPtr($struct), _     "int", 1) If @error Then     ConsoleWrite("Error: " & @error & @CRLF)     exit 1 Else     ConsoleWrite("Success: " & $aCall[0] & @CRLF) EndIf
      If I ran the AU3-Script with SciTE I get the following output:
      !>12:00:00 AutoIt3.exe ended.rc:-1073741783 Can someone point me into the right direction. I must admit, that I'm very new to handling DLL-Calls and structs.
      But I've read down the forum threads and the AutoIt help.
      Thanks in advance.