Need help calling a proprietary C DLL from Python

Craig craigm3604 at gmail.com
Tue Mar 25 11:24:13 EDT 2008


On Mar 25, 2:02 am, Dennis Lee Bieber <wlfr... at ix.netcom.com> wrote:
> On Mon, 24 Mar 2008 15:21:11 -0700 (PDT), Craig <craigm3... at gmail.com>
> declaimed the following in comp.lang.python:
>
> > And this is what I got:
> > VmxGet test - looking for valid record...
> > Before -    PriKey = 0x0044F56C,    SecKey = 0x0044F534
> >          ci_PriKey = 0x0044F56C, ci_SecKey = 0x0044F534
> > After -    PriKey = 0x0044F56C,    SecKey = 0x0044F534
> >         ci_PriKey = 0x0043D49C, ci_SecKey = 0x0043D484
>
>         So VmxGet() DID allocate new BSTR structures.
>
>         It might be interesting to extract the length data that is part of
> the BSTR and compare.
>
>         ctypes.string_at(PriKey - 4, 4) #if I recall the arguments
> vs
>         ctypes.string_at(ci_PriKey - 4, 4)
>
>         If the second (after conversion to integer) is larger than the
> former, it could mean that the routine checks what is passed in to
> ensure enough storage space, and if it won't fit, does the allocation.
>
>         If it were always going to do an allocation, there would have been
> no excuse for /reading/ the passed in structure length.
> --
>         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/

I changed to the following to followup on the length data:
printf ("Before -    PriKey = 0x%8.8X,    SecKey = 0x%8.8X\n", PriKey,
SecKey)
printf ("         ci_PriKey = 0x%8.8X, ci_SecKey = 0x%8.8X\n",
ci_PriKey.value, ci_SecKey.value)
res = VmxGet( byref(hwmcb), byref(SecIndex), byref(Option),
byref(c_void_p(SrchKey)), byref(ci_SecKey), byref(ci_PriKey),
TypeDef )
printf ("After -    PriKey = 0x%8.8X,    SecKey = 0x%8.8X\n", PriKey,
SecKey)
printf ("        ci_PriKey = 0x%8.8X, ci_SecKey = 0x%8.8X\n",
ci_PriKey.value, ci_SecKey.value)
print ord(string_at(PriKey - 4, 1)), ord(string_at(PriKey - 3, 1)),
ord(string_at(PriKey - 2, 1)), ord(string_at(PriKey - 1, 1))
print ord(string_at(ci_PriKey.value - 4, 1)),
ord(string_at(ci_PriKey.value - 3, 1)), ord(string_at(ci_PriKey.value
- 2, 1)), ord(string_at(ci_PriKey.value - 1, 1))
And, got:
Before -    PriKey = 0x0028B6FC,    SecKey = 0x0028B6C4
         ci_PriKey = 0x0028B6FC, ci_SecKey = 0x0028B6C4
After -    PriKey = 0x0028B6FC,    SecKey = 0x0028B6C4
        ci_PriKey = 0x0027D284, ci_SecKey = 0x0027D26C
41 0 0 0
7 0 0 0
Which makes sense for two reasons:
1. It would only return the non-space-filled part of the returned key.
2. At least from VB6, the variable does not even have to be used
before the call.

I have gone on to design a function for printing the contents as
fields in a Structure.
def DCOD_Print():
    temp = unpack(DecoderRecordFormat, TypeDef.raw)
    DCOD = DecoderRecord(temp[0], temp[1], temp[2], temp[3], temp[4],
temp[5])
    print "       DistID = \x22%s\x22" % DCOD.DistID
    print "     YearCode = \x22%s\x22" % DCOD.YearCode
    print "  AccountType = \x22%s\x22" % DCOD.AccountType
    print "AccountNumber = \x22%s\x22" % DCOD.AccountNumber
    print "  Description = \x22%s\x22" % DCOD.Description
    print "       Unused = \x22%s\x22" % DCOD.Unused
    return

class DecoderRecord(Structure):
      _fields_ = [
                   ("DistID", c_char_p),
                   ("YearCode", c_char_p),
                   ("AccountType", c_char),
                   ("AccountNumber", c_char_p),
                   ("Description", c_char_p),
                   ("Unused", c_char_p)
                 ]
DecoderRecordFormat = "3s4ss32s32s56s"

Then, a simple:
print DCOD_Print()
parses the record into its fields, and displays those fields.

In other files, some of those fields are VB6 currency types, which
have been described as 8-byte integers with an implied 4 decimal
places (which I guess would be __int64 or c_longlong and then divide
by 10,000, or simply put a decimal point 4 away from the end).

Any ideas on how best to process this type of data in Python?



More information about the Python-list mailing list