Need help calling a proprietary C DLL from Python

Craig craigm3604 at gmail.com
Sat Mar 22 22:05:31 EDT 2008


On Mar 22, 9:40 pm, Dennis Lee Bieber <wlfr... at ix.netcom.com> wrote:
> On Sat, 22 Mar 2008 15:12:47 -0700 (PDT), Craig <craigm3... at gmail.com>
> declaimed the following in comp.lang.python:
>
>
>
>
>
> > Anyway, I have the following for "types":
> > LPBSTR = POINTER(c_void_p)
> > HANDLE = POINTER(POINTER(c_long))
> > LPHANDLE = POINTER(HANDLE)
> > LPSHORT = POINTER(c_short)
> > LPVSTATS = POINTER(c_void_p)
> > c_string = c_char_p
> > LPSTR = c_string
>
> > I guess passing a structure is out of the question. So, I tried a
> > string (something - just to get the data back):
> > #short FAR PASCAL VmxInfo(LPHANDLE lpDatasetNumber, LPVSTATS
> > lpvstats);
> > VmxInfo = windll.vbis5032.VmxInfo
> > VmxInfo.restype = c_short
> > VmxInfo.argtypes = [LPHANDLE, LPSTR]
> > VsamInfo = create_string_buffer("12345678901234567890123456789012")
> > printf ("VsamInfo = \x22%s\x22\n", VsamInfo.raw)
> > print "Ready to call (Library = " + find_library("vbis5032") + ") ..."
> > res = VmxInfo( byref(hwmcb), byref(VsamInfo) )
> > And I get:
> > Ready to call (Library = C:\Windows\vbis5032.dll) ...
> > Traceback (most recent call last):
> >   File "C:\temp\vbisam_test_2.py", line 101, in <module>
> >     res = VmxInfo( byref(hwmcb), byref(VsamInfo) )
> > ctypes.ArgumentError: argument 2: <type 'exceptions.TypeError'>: wrong
> > type
>
>         Did you try just passing the buffer, rather than nesting a "byref"
>
> http://docs.python.org/lib/ctypes-passing-pointers.html
>
> Note how the string buffer parameter has NO odd games on it. This
> especially applies to the other call below, for PriKey and the other
> BSTR *... term
>
>         As for passing a structure... Well, I'd suggest using struct.pack to
> push arguments into such a structure (though it it is using pointers to
> other items it may get tricky), using create_string_buffer to make the
> Python string "structure" a C-memory block, passing that, and if needed,
> struct.unpack the item after the call.
> --
>         Wulfraed        Dennis Lee Bieber               KD6MOG
>         wlfr... at ix.netcom.com             wulfr... at bestiaria.com
>                 HTTP://wlfraed.home.netcom.com/
>         (Bestiaria Support Staff:               web-a... at bestiaria.com)
>                 HTTP://www.bestiaria.com/


Based on your input, I changed:
LPSTR = c_char_p
VmxGet = windll.vbis5032.VmxGet
VmxGet.restype = c_short
VmxGet.argtypes = [LPHANDLE, LPSHORT, LPSHORT, LPBSTR, LPBSTR, LPBSTR,
LPSTR]
SrchKey =
windll.oleaut32.SysAllocStringByteLen("MSD19PH
\x00", 41)
SecKey =
windll.oleaut32.SysAllocStringByteLen("1234567890123456789012345678901234567890\x00",
41)
PriKey =
windll.oleaut32.SysAllocStringByteLen("1234567890123456789012345678901234567890\x00",
41)
TypeDef = create_string_buffer(128)
TypeDef.raw = "X".center(128, "X")
print "Ready to call (Library = " + find_library("vbis5032") + ") ..."
res = VmxGet( byref(hwmcb), byref(SecIndex), byref(Option),
byref(c_void_p(SrchKey)), byref(c_void_p(SecKey)),
byref(c_void_p(PriKey)), TypeDef )
printf ("After - res = %#x (%d), SecIndex = %d, Option = %d, hwmcb = %d
\n", res, res, SecIndex, Option, hwmcb)
printf ("SrchKey = \x22%s\x22\nSeckey = \x22%s\x22\nPriKey = \x22%s
\x22\nTypeDef = \x22%s\x22\n", SrchKey, SecKey, PriKey, TypeDef.raw)


I got back exactly what I expected for TypeDef, but SecKey and PriKey
were what I initialized them to , not what should have been returned.

Do you mean that I should change any string that is expected to be
changed by the dll to a create_string_buffer type (LPSTR) instead of a
windll.oleaut32.SysAllocStringByteLen type (LPBSTR) and then simply
list it in the call instead of byref, as I did with TypeDef?

Can it really be that simple?

As for the structure:
class VSTATS(Structure):
      _fields_ = [
                   ("nrecords", c_long),
                   ("gps_used", c_short),
                   ("gps_unused", c_short),
                   ("max_key_len", c_short),
                   ("grp_size", c_long),
                   ("init_alloc", c_short),
                   ("cr_opts", c_short),
                   ("free_prop_area", c_short),
                   ("format", c_void_p),
                   ("reserved", c_void_p)
                 ]
vStats = VSTATS(1, 2, 3, 4, 5, 6, 7, 8)
can I just use a create_string_buffer (LPSTR) and parse things up via
substrings after the call returns?



More information about the Python-list mailing list