By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
438,427 Members | 1,379 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 438,427 IT Pros & Developers. It's quick & easy.

with ctypes, how to parse a multi-string

P: n/a

Hi,

I am currently dealing with ctypes, interfacing with winscard libbrary
(for smart card access).

Several APIs (e.g. SCardListReaderGroupsW ) take a pointer to an
unicode string as a parameter , which points at function return to a
"sequence" of unicode strings, NULL terminated. The last string is
double NULL terminated. (of course buffer length is also returned as
another parameter).

e.g. it could return something like
'group1\x00group2\x00group3\x00\x00'

What should I use as argtypes to my function prototype in order to
gain access to the full list? using c_wchar_p works, but it resolves
the string until it reaches the first \x00, resulting in having access
to the first entry of the list only.

as reference, my current ctypes mapping for this API is:

# extern WINSCARDAPI LONG WINAPI
# SCardListReaderGroupsW(
# IN SCARDCONTEXT hContext,
# OUT LPWSTR mszGroups,
# IN OUT LPDWORD pcchGroups);

_ListReaderGroups = scardlib.SCardListReaderGroupsW
_ListReaderGroups.argtypes = [ c_ulong, c_void_p, c_void_p ]
_ListReaderGroups.restype = c_ulong

Calling the API looks like:

pcchreadergrp = c_long(SCARD_AUTOALLOCATE)
groups = c_wchar_p()

_ListReaderGroups( ctx, byref(groups), byref(pcchreadergrp))
Should I be using some array/ctypes.cast() combination to gain access
to all returned characters?

May 30 '07 #1
Share this Question
Share on Google+
2 Replies


P: n/a
Eric schrieb:
Hi,

I am currently dealing with ctypes, interfacing with winscard libbrary
(for smart card access).

Several APIs (e.g. SCardListReaderGroupsW ) take a pointer to an
unicode string as a parameter , which points at function return to a
"sequence" of unicode strings, NULL terminated. The last string is
double NULL terminated. (of course buffer length is also returned as
another parameter).

e.g. it could return something like
'group1\x00group2\x00group3\x00\x00'

What should I use as argtypes to my function prototype in order to
gain access to the full list? using c_wchar_p works, but it resolves
the string until it reaches the first \x00, resulting in having access
to the first entry of the list only.
A c_wchar_p instance represent a (one!) zero-terminated string, as you
already know. A POINTER(c_wchar) instance is more flexible, you should
use that instead. It can be indexed/sliced with arbitrary indexes.

Here is a simple script to get you started:

"""
from ctypes import *

# Normally, the function call will fill the buffer:
buf = create_unicode_buffer("first\0second\0third\0")

# The pointer you will pass to the function call
ptr = cast(buf, POINTER(c_wchar))

# function call omitted

# Print the raw result
print ptr[:len(buf)]

# Print a list of strings
print ptr[:len(buf)].split("\0")
"""

Thomas

May 31 '07 #2

P: n/a
On May 31, 2:52 pm, Thomas Heller <thel...@ctypes.orgwrote:
Eric schrieb:
Hi,
I am currently dealing with ctypes, interfacing with winscard libbrary
(for smart card access).
Several APIs (e.g. SCardListReaderGroupsW ) take a pointer to an
unicode string as a parameter , which points at function return to a
"sequence" of unicode strings, NULL terminated. The last string is
double NULL terminated. (of course buffer length is also returned as
another parameter).
e.g. it could return something like
'group1\x00group2\x00group3\x00\x00'
What should I use as argtypes to my function prototype in order to
gain access to the full list? using c_wchar_p works, but it resolves
the string until it reaches the first \x00, resulting in having access
to the first entry of the list only.

A c_wchar_p instance represent a (one!) zero-terminated string, as you
already know. A POINTER(c_wchar) instance is more flexible, you should
use that instead. It can be indexed/sliced with arbitrary indexes.

Here is a simple script to get you started:

"""
from ctypes import *

# Normally, the function call will fill the buffer:
buf = create_unicode_buffer("first\0second\0third\0")

# The pointer you will pass to the function call
ptr = cast(buf, POINTER(c_wchar))

# function call omitted

# Print the raw result
print ptr[:len(buf)]

# Print a list of strings
print ptr[:len(buf)].split("\0")
"""

Thomas
Thanks Thomas, it works as expected!

Regards,

Eric

May 31 '07 #3

This discussion thread is closed

Replies have been disabled for this discussion.