467,887 Members | 1,604 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 467,887 developers. It's quick & easy.

with ctypes, how to parse a multi-string


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
  • viewed: 2482
Share:
2 Replies
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
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.

Similar topics

3 posts views Thread by Anton Vredegoor | last post: by
6 posts views Thread by Dave Kuhlman | last post: by
3 posts views Thread by chris | last post: by
2 posts views Thread by cantankerousoldgit | last post: by
2 posts views Thread by mclaugb | last post: by
1 post views Thread by moreati | last post: by
2 posts views Thread by Philluminati | last post: by
reply views Thread by MrMoon | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.