Jump to content

Problem with calling DLL functions to return structure pointers


Recommended Posts

Hello, everyone. I'm very sorry. My mother tongue is not English. I asked questions through machine translation

This is a function from the XXHASH library, derived from https://github.com/Cyan4973/xxHash/

I generated xxhash.dll using VS2022 and tested the DLL function in other languages to be normal. It is now converted to an AUTOIT call exception. May I ask why?

 

#cs

typedef uint64_t XXH64_hash_t;
typedef uint32_t XXH32_hash_t;

struct XXH64_state_s {
   XXH64_hash_t total_len;    /*!< Total length hashed. This is always 64-bit. */
   XXH64_hash_t v[4];         /*!< Accumulator lanes */
   XXH64_hash_t mem64[4];     /*!< Internal buffer for partial reads. Treated as unsigned char[32]. */
   XXH32_hash_t memsize;      /*!< Amount of data in @ref mem64 */
   XXH32_hash_t reserved32;   /*!< Reserved field, needed for padding anyways*/
   XXH64_hash_t reserved64;   /*!< Reserved field. Do not read or write to it, it may be removed. */
};   

typedef struct XXH64_state_s XXH64_state_t;  


XXH_PUBLIC_API XXH64_state_t* XXH64_createState(void)
{
    return (XXH64_state_t*)XXH_malloc(sizeof(XXH64_state_t));
}


#ce

#include <StructureConstants.au3>
#include <Memory.au3>

Global $XXH64_STATE_T  = "uint64 total_len; uint64 v[4]; uint64 mem64[4]; uint32 memsize; uint32 reserved32; uint64 reserved64;"

Func XXH64_createState()
    Local $pState = DllStructCreate($XXH64_STATE_T)
    Local $pResultPtr = DllCall("xxhash.dll", "ptr", "XXH64_createState")

    If @error Then Return $pState

    $pState = Ptr($pResultPtr[0])
    
    _MemGlobalAlloc(DllStructGetSize($pState))
    DllCall("kernel32.dll", "ptr", "CopyMemory", "ptr", $pState, "ptr", Ptr($pResultPtr[0]), "uint", DllStructGetSize($pState))
    ConsoleWrite("pResult[0]: " & $pState & ", total_len: " & DllStructGetData($pState, "total_len") & ", v[0]: " & DllStructGetData($pState, "v", 1) & ", v[1]: " & DllStructGetData($pState, "v", 2) & ", ..." & @CRLF)

    Return $pState
EndFunc
      

Local $pState = XXH64_createState()
 

 

 

Link to comment
Share on other sites

#if (defined(XXH_INLINE_ALL) || defined(XXH_PRIVATE_API)) \
    && !defined(XXH_INLINE_ALL_31684351384)
   /* this section should be traversed only once */
#  define XXH_INLINE_ALL_31684351384
   /* give access to the advanced API, required to compile implementations */
#  undef XXH_STATIC_LINKING_ONLY   /* avoid macro redef */
#  define XXH_STATIC_LINKING_ONLY
   /* make all functions private */
#  undef XXH_PUBLIC_API
#  if defined(__GNUC__)
#    define XXH_PUBLIC_API static __inline __attribute__((unused))
#  elif defined (__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
#    define XXH_PUBLIC_API static inline
#  elif defined(_MSC_VER)
#    define XXH_PUBLIC_API static __inline
#  else
     /* note: this version may generate warnings for unused static functions */
#    define XXH_PUBLIC_API static
#  endif

 

Link to comment
Share on other sites

If the structure pointer returns normal, then the value of the structure variable should not be 0

 

#include <StructureConstants.au3>
#include <Memory.au3>

Global $XXH64_STATE_T  = "uint64 total_len; uint64 v[4]; uint64 mem64[4]; uint32 memsize; uint32 reserved32; uint64 reserved64;"

Func XXH64_createState()
    Local $pResultPtr = DllCall("xxhash.dll", "ptr:cdecl", "XXH64_createState")
    Local $pState = Ptr($pResultPtr[0])

    If @error Then Return $pState

    _MemGlobalAlloc(DllStructGetSize($pState))
    DllCall("kernel32.dll", "ptr", "CopyMemory", "ptr", $pState, "ptr", $pResultPtr[0], "uint", DllStructGetSize($pState))
;~    ConsoleWrite("pResult[0]: " & $pState & ", total_len: " & DllStructGetData($pState, "total_len") & ", v[0]: " & DllStructGetData($pState, "v", 1) & ", v[1]: " & DllStructGetData($pState, "v", 2) & ", ..." & @CRLF)
ConsoleWrite("pResult[0]: " & $pState & "total_len: " & DllStructGetData($pState, "total_len") & ", v[0]: " & DllStructGetData($pState, "v", 1) & ", v[1]: " & DllStructGetData($pState, "v", 2) & ", ..." & @CRLF)
    Return $pState
EndFunc

Local $pState = XXH64_createState()
 

 

 

The result of the code output now is: pResult[0]: 0x00000197D7CBA170total_len: 0, v[0]: 0, v[1]: 0, ...

Link to comment
Share on other sites

Did adding the "cdecl" help? If so, then I suspect that the issue is now in the code following the DllCall command. See if this works any better --

#include <StructureConstants.au3>
#include <Memory.au3>

Global $XXH64_STATE_T  = "uint64 total_len; uint64 v[4]; uint64 mem64[4]; uint32 memsize; uint32 reserved32; uint64 reserved64;"

Local $pState = XXH64_createState()

Func XXH64_createState()
    Local $pResult = DllCall("xxhash.dll", "ptr:cdecl", "XXH64_createState")

    Local $tStruct = DllStructCreate($XXH64_STATE_T, $pResult[0])
    
    ConsoleWrite("$pResult[0]: " & $pResult[0] & ", total_len: " & DllStructGetData($tStruct, "total_len") & ", v[0]: " & DllStructGetData($tStruct, "v", 1) & ", v[1]: " & DllStructGetData($tStruct, "v", 2) & ", ..." & @CRLF)
    Return $pResult[0]
EndFunc

 

Link to comment
Share on other sites

Had a quick look at the code; it's definitely cdecl calling convention, and since the call returns a 64-bit ptr, you'll want to run AutoIt in x64 mode.

Link to comment
Share on other sites

It runs under X64, but the output result is unstable, and the value of 0 is often obtained. It is normal to call it in C

 

1924229750_.gif.c68217d33a6efaa182a9c1db98b8a1a4.gif

 

#include <StructureConstants.au3>
#include <Memory.au3>

Global $XXH64_STATE_T  = "uint64 total_len; uint64 v[4]; uint64 mem64[4]; uint memsize; uint reserved32; uint64 reserved64;"

Local $pState = XXH64_createState()

Func XXH64_createState()
    Local $pResult = DllCall("xxhash.dll", "ptr:cdecl", "XXH64_createState")

    Local $tStruct = DllStructCreate($XXH64_STATE_T, $pResult[0])
    ConsoleWrite("$tStruct size: " & DllStructGetSize($tStruct) &@CRLF)
    ConsoleWrite("$pResult[0]: " & $pResult[0] & ", total_len: " & DllStructGetData($tStruct, "total_len") & ", v[0]: " & DllStructGetData($tStruct, "v", 1) & ", v[1]: " & DllStructGetData($tStruct, "v", 2) & ", ..." & @CRLF)
    Return $pResult[0]
EndFunc

 

xxhash.zip

Link to comment
Share on other sites

are you sure XXH64_createState->total_len should return a value? can you share a C++ example? I think issue could be due to the way compiler handle structure(while returning)

So probably You need to create a wrapper function for XXH64_createStateWrapper( *struct) and pass the AutoIt structure. so you could later do memcpy to copy XXH64_createState returned structure to your AutoIt structure.

It's just a mind I had being long time without touching C/C++.

 

Saludos

Link to comment
Share on other sites

#define BUFFER_SIZE 1024*64

uint64_t xxhsum_stream(FILE* fp) {
    
    XXH64_state_t* const state = XXH64_createState();
    printf("%llu %llu %llu %u %u %llu\n", state->total_len, state->v[0], state->mem64[0], state->memsize, state->reserved32, state->reserved64);

    XXH64_reset(state, 0);
    uint8_t buffer[BUFFER_SIZE];
    size_t read_size;
    while ((read_size = fread(buffer, 1, BUFFER_SIZE, fp)) != 0) {
        XXH64_update(state, buffer, read_size);
    }
    return XXH64_digest(state);
}

 

_20230510230018.png.357641abce2bceb6e1e3f2811302a8d4.png

Please refer to the following address for the detailed function structure. Thank you very much

https://github.com/Cyan4973/xxHash/

Edited by kraotn
Link to comment
Share on other sites

  • 1 year later...

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...