On Mar 23, 7:59 pm, Dennis Lee Bieber <[EMAIL PROTECTED]> wrote: > On Sun, 23 Mar 2008 14:24:52 -0700 (PDT), Craig <[EMAIL PROTECTED]> > declaimed the following in comp.lang.python: > > > > > This dll was designed to be used from either C or Visual Basic 6. > > > I have the declare statements for VB6, if that helps. > > Probably not that much -- I'd bet it's full of variant records <G> > > > > > Based on the results I have so far (and I have tried MANY permutations > > like trying to use the LPSTR for SecKey and PriKey which are returned > > as is TypeDef), it looks like SecKey and PriKey are being used as data > > instead of pointers. > > > For this, I try: > > LPSTR = c_char_p > > VmxGet.argtypes = [LPHANDLE, LPSHORT, LPSHORT, LPBSTR, LPSTR, LPBSTR, > > LPSTR] > > SrchKey = > > windll.oleaut32.SysAllocStringByteLen("MSD19DN > > \x00", 41) > > SecKey = create_string_buffer(41) > > SecKey.raw = "1234567890123456789012345678901234567890" > > PriKey = > > windll.oleaut32.SysAllocStringByteLen("ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234\x00", > > 41) > > TypeDef = create_string_buffer(128) > > TypeDef.raw = "X".center(128, "X") > > res = VmxGet( byref(hwmcb), byref(SecIndex), byref(Option), > > byref(c_void_p(SrchKey)), SecKey, byref(c_void_p(PriKey)), TypeDef ) > > and I get: > > Traceback (most recent call last): > > File "C:\temp\vbisam_test_2.py", line 158, in <module> > > res = VmxGet( byref(hwmcb), byref(SecIndex), byref(Option), > > byref(c_void_p(S > > rchKey)), SecKey, byref(c_void_p(PriKey)), TypeDef ) > > WindowsError: exception: access violation reading 0x3433322D > > > I notice that SecKey.raw starts with "1234" and the exception address > > is 0x3433322D, which is "432-". > > 0x2D is 4 less than the expected 0x31... > > > > > And, changing to: > > VmxGet.argtypes = [LPHANDLE, LPSHORT, LPSHORT, LPBSTR, LPBSTR, LPSTR, > > LPSTR] > > PriKey = create_string_buffer(41) > > PriKey.raw = "ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234" > > res = VmxGet( byref(hwmcb), byref(SecIndex), byref(Option), > > byref(c_void_p(SrchKey)), byref(c_void_p(SecKey)), PriKey, TypeDef ) > > I then get: > > Traceback (most recent call last): > > File "C:\temp\vbisam_test_2.py", line 159, in <module> > > res = VmxGet( byref(hwmcb), byref(SecIndex), byref(Option), > > byref(c_void_p(S > > rchKey)), byref(c_void_p(SecKey)), PriKey, TypeDef ) > > WindowsError: exception: access violation reading 0x4443423D > > > I notice that PriKey.raw starts with "ABCD" and the exception address > > is 0x4443423D, which is "DBC=". > > ... and 0x3D is 4 less than the expected 0x41 > > Which leads me to suspect that BSTR are a structure, not a plain > string, in which the address given is supposed to be prefaced with a > length value. IOWs, something like: > > |----|--------------------------------------| > ^ ^ C-string data > | |Address to be passed > |(address - 4) to get to a length count field > > Confirmed:http://msdn2.microsoft.com/en-us/library/ms221069(VS.85).aspx > > (the URL is from HTTP through to the end, including .aspx) > > Creating such may not be difficult -- but passing it to the DLL > could be. I don't know if ctypes allows pointer arithmetic. > > ctypes OLESTR is a c_wchar_p, but that is still a c-style string with no > length prefix. > > The only mention of BSTR in the win32 extensions is in text that > implies that the win32 extension library takes care of converting > from/to BSTR and Python strings transparently -- but that won't work for > your third-party library I suspect. > > Might have to beg the author(s) of ctypes to add a BSTR type to the > list of those supported... as I can find no means of tweaking the > address computed by byref() to point somewhere into a structure rather > than the beginning of the structure. > > >>> pk = ctypes.windll.oleaut32.SysAllocStringByteLen("1234567890", 12) > >>> pk > 1373844 > >>> id(pk) > 18941724 > >>> ctypes.string_at(pk) > '1234567890' > >>> ctypes.string_at(pk-4, 20) > > '\x0c\x00\x00\x001234567890\x00\x01\x00\x00\x00\x00' > > > > Okay, the return value from SysAlloc... IS the integer representing > the address of a BSTR structure (IE, the address four bytes in from the > real memory start)... Note how backing up 4 bytes reveals the BSTR > length field > > What happens if you just pass that item as-is, no byref(), no > conversion to ctypes pointer types... > > PriKey = ctypes.windll.oleaut32.SysAllocStringByteLen("1234567890", 41) > SecKey = ctypes.windll.oleaut32.SysAllocStringByteLen("1234567890", 41) > > res = VmxGet( byref(hwmcb), > byref(SecIndex), > byref(Option), > byref(c_void_p(SrchKey)), > SecKey, > PriKey, > TypeDef ) > > >>> PriKey = ctypes.windll.oleaut32.SysAllocStringByteLen("1234567890", 41) > >>> ctypes.string_at(PriKey, 41) > > "1234567890\x00\x01:\x00\x00\x00\xb6\x01\x00\x000\x99#\x01\xe0\x94\x1a\x1e\x0b\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00'">>> > ctypes.string_at(PriKey-4, 41+4) > > ")\x00\x00\x001234567890\x00\x01:\x00\x00\x00\xb6\x01\x00\x000\x99#\x01\xe0\x94\x1a\x1e\x0b\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00'" > > >>> ord(")") > 41 > > You'll need to use the .string_at() or .wstring_at() functions to > extract any data changed by the call. Should not be a Python > immutability problem as all "you" allocated in Python is the integer > holding the address. You may need to call a Sys... function to free the > memory that had been allocated -- Python doesn't know about it. > -- > Wulfraed Dennis Lee Bieber KD6MOG > [EMAIL PROTECTED] [EMAIL PROTECTED] > HTTP://wlfraed.home.netcom.com/ > (Bestiaria Support Staff: [EMAIL PROTECTED]) > HTTP://www.bestiaria.com/
The VB6 Declare is: Declare Function VmxGet Lib "vbis5032.DLL" (DatasetHandle&, SecIndexField%, Options%, SelectorKey$, RSecondaryKey$, RPrimaryKey$, RRecordVariable As Any) As Integer The only variant is the RRecordVariable, which is actually meant to be a Type structure. Anyway, I thought maybe there was a clue in here that I am missing. Back to Python. I ran with the following: VmxGet.argtypes = [LPHANDLE, LPSHORT, LPSHORT, LPBSTR, LPSTR, LPSTR, LPSTR] SrchKey = windll.oleaut32.SysAllocStringByteLen("MSD19DN \x00", 41) SecKey = windll.oleaut32.SysAllocStringByteLen("1234567890123456789012345678901234567890\x00", 41) PriKey = windll.oleaut32.SysAllocStringByteLen("ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234\x00", 41) TypeDef = create_string_buffer(128) TypeDef.raw = "X".center(128, "X") res = VmxGet( byref(hwmcb), byref(SecIndex), byref(Option), byref(c_void_p(SrchKey)), SecKey, PriKey, TypeDef ) And, now I get: Traceback (most recent call last): File "C:\temp\vbisam_test_2.py", line 156, in <module> res = VmxGet( byref(hwmcb), byref(SecIndex), byref(Option), byref(c_void_p(S rchKey)), SecKey, PriKey, TypeDef ) ctypes.ArgumentError: argument 5: <type 'exceptions.TypeError'>: wrong type So, now the problem is with: VmxGet.argtypes = [LPHANDLE, LPSHORT, LPSHORT, LPBSTR, LPSTR, LPSTR, LPSTR] I am not sure what to put for arguments 5 and 6 now. I realized the need to release the BSTRs myself, and already included: windll.oleaut32.SysFreeString(SrchKey) windll.oleaut32.SysFreeString(SecKey) windll.oleaut32.SysFreeString(PriKey) at the end of the program. I have no problem using .string_at() to extract the returned values - once the .argtypes let the call execute. In case this helps, here is an excerpt from a C program that was provided with the dll: typedef struct tagMYREC { char name[51]; // 1 xref generated name key char lastname[31]; // 2 last name char firstname[21]; // 3 first name char address[41]; // 4 address char city[31]; // 5 xref city key char state[3]; // 6 xref state char zip[11]; // 7 xref zip code char phone[21]; // 8 xref phone number BSTR notes; // 9 notes } MYREC; typedef MYREC FAR * LPMYREC; short rc; // return code (from VB/ISAM function calls) static HANDLE nDatasetNumber; static short cur_index; static short GetOpt; static BSTR Dummy; static BSTR Throwaway; static BSTR PrimaryKey; static MYREC myrec; rc = VmxGet(&nDatasetNumber, // int DatasetNumber // VIS_BUSY ? &cur_index, // int SelectedIndex &GetOpt, // int OptionParameter &Dummy, // Don't need a Selector param with these options &Throwaway, // Don't need returned index entry in this case &PrimaryKey, // LPBSTR lpPriKey (void *) &myrec); // LPVOID lpRecordStructure For someone who knows C and Python, this may provide a clue to the BSTR passing/return problem. -- http://mail.python.org/mailman/listinfo/python-list