Flippie Coetser
Flippie Coetser

Reputation: 95

Possible incorrect use of Pointers in ctypes. Unable to get expected response

Given the following c code snippet

#include<stdio.h>
#include "mcp2221_dll_um.h"

int main(void) {
    wchar_t LibVersion[10];
    int response = 0;
    int error = 0;

    response = Mcp2221_GetLibraryVersion(LibVersion);

    if(response == 0) {
        printf("Library (DLL) version: %ls \n",LibVersion);
    } else {
        error = Mcp2221_GetLastError();
        printf("Version can't be found, version: %d, error %d\n", response, error);

    }
}

with the function signature as defined in mcp2221_dll_um.h file

MCP2221_DLL_UM_API int CALLING_CONVENTION Mcp2221_GetLibraryVersion(wchar_t *version); 

I compile the source using gcc: gcc -o test test.c -L. -lmcp2221_dll_um_x64
and run the executable: ./text.exe
then I get the following output: Library (DLL) version: 2.2b

GREAT it works as expected!

Now I would like to use python and ctypes to produce the same results.
So I wrote the following python code snippet

from ctypes import *

library = WinDLL("./mcp2221_dll_um_x64.dll")
library.Mcp2221_GetLibraryVersion.restype = c_int
library.Mcp2221_GetLibraryVersion.argtypes = [POINTER(c_wchar_p)]

LibVersion = c_wchar_p()

results = library.Mcp2221_GetLibraryVersion(LibVersion)

print("results: ", results)
print("LibVersion: ", LibVersion)

and run the code: python test.py and get the following output

results: 0
LibVersion: c_wchar_p(27584762469223794)

The results 0 tells me the request was successful, but I am not sure how I can convert the LibVersion into a readable string which equals 2.2b like I get from running the c sample.

Please help me out here, I am using pointers the wrong way? or some other mistake?

Upvotes: 0

Views: 147

Answers (1)

Mark Tolonen
Mark Tolonen

Reputation: 177471

c_wchar_p is a pointer and equivalent to wchar_t* in C. Just use .argtypes = [c_wchar_p].

Another issue is the API being called is using the wchar_t* buffer as an out parameter, so you need to allocate a buffer to pass. This should work:

from ctypes import *

library = WinDLL("./mcp2221_dll_um_x64.dll")
library.Mcp2221_GetLibraryVersion.restype = c_int
library.Mcp2221_GetLibraryVersion.argtypes = c_wchar_p,

LibVersion = create_unicode_buffer(10)
results = library.Mcp2221_GetLibraryVersion(LibVersion)

print("results: ", results)
print("LibVersion: ", LibVersion.value)

Note that LibVersion.value displays the null-terminated Unicode string in the buffer. If you needed to access the raw data you can use indexing or just copy the whole array out to a string with slicing:

>>> s=ctypes.create_unicode_buffer(10)
>>> s
<ctypes.c_wchar_Array_10 object at 0x000001E63085C7C8>
>>> s.value
''
>>> s[:]
'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

Upvotes: 1

Related Questions