Don't understand how to work with null_mut(), transmute(), *mut i8

Hi,

I'm calling this SCardStatusA Windows API:
https://learn.microsoft.com/en-us/windows/win32/api/winscard/nf-winscard-scardstatusa

The second argument is:

[out]               LPSTR       mszReaderNames,

LPSTR is basically *mut i8

It only works if I do this:

let mszReaders: LPSTR = null_mut();
let ptr_trans =  transmute(&mszReaders);
SCardStatusA(hCard, ptr_trans, SCARD_AUTOALLOCATE,

Then I can get the result from mszReaders, not the ptr_trans .

If I use mszReaders directly with the API, it gets "Access Violation" error.

After transmute(&mszReaders), the ptr_trans is not null and *ptr_trans = 0;

Would some one help to explain why I couldn't use mszReaders directly?

Why

Is there a way to avoid transmute() in this case?

Thanks a lot.

This is a classic mistake.

No it's not. The very documentation you linked to says that if you use SCARD_AUTOALLOCATE as the length, then it should be a pointer to a pointer. It's basically an *mut *mut i8. Just think about it – if you only had a single level of indirection, it would be impossible for the API to fill in your buffer without you pre-allocating space for all the characters, as it couldn't modify the pointer itself.

Thus, the solution has nothing to do with transmute(), and everything to do with the fact that in the second case, you are passing the address of your null pointer itself, which means that it will be changed to a non-null, valid pointer, that points to a buffer (that is allocated by the function).

So, just do this:

let mszReaders: LPSTR = null_mut();
let ptr = &mut mszReaders as *mut _ as LPSTR;
SCardStatusA(hCard, ptr_trans, SCARD_AUTOALLOCATE, ...);

No transmute needed, as pointers can be cast directly. Incidentally, you should never transmute pointers.

1 Like

I think that should be &mut, otherwise the ffi function would be modifying the variable through a shared reference, right?

Right, fixed it, thanks!

Thanks a lot. The *mut *mut i8 and pointer of byte array pointer explained everything.