in reply to Re^9: WIN32::API and void*
in thread WIN32::API and void*
Do not pack $LeftTable and $RightTable. They should be 12345, not "\x12\x34....". myTable is a void * and is a HANDLE/pointer sized integer, myTable * is a void **. I saw you create $packedOutputTable from ,$outputTable with CreateTable but never checked $outputTable for null/0/false. $pointerToCount looks fine. I don't think the 2 doubles cause problems at this point.
Good, so I only have to work out wich letter to use in pack to pass $LeftTable and $RightTable. I'll have a go tomorrow and let you know (btw thanks again, I'm learning a lot). In reference with $packedOutputTable:
I understand that's the right way to pass a void**.my $outputTable = $CreateTable->Call(); my $packedOutputTable = pack('J',$outputTable);
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^11: WIN32::API and void*
by bulk88 (Priest) on Jul 26, 2012 at 19:06 UTC | |
then do something like I still would like to see a Dumper() of the parameters you passed to myTableCompare. About your DLL, do you have the source code to it or not? If you have the source code for that DLL you can use a C debugger with symbols, you could figure out in about a minute why it crashed. Even without the source code to that DLL, you can figure out if it crashed inside the DLL, or Win32::API/Perl crashed from C stack corruption (the latter only happens with stdcall functions, cdecls very very rarely corrupt the C stack, but they may see garbage parameters if they are prototyped incorrectly by the caller, a wrong prototype with a stdcall is 100% fatal). Most MS DLLs, the C functions always "validate" their parameters, with SEH or IsBadReadPtr and friends, so when you pass a NULL ptr, or a "(char *)1234", they fail with GLR=ERROR_INVALID_PARAMETER, they DONT crash. Non-MS DLLs, its upto the programmer of that DLL on what to do, usually they don't do what MS does and simply crash. If it works in C, its guaranteed that, somehow, someway, Win32::API my non-CPAN 0.69-0.71 will work. I say my non-CPAN versions because 0.68 for example, if the return type is a float, the C function is never called (bug in 0.68). If you want to see pushing Win32::API 0.68 to its limits (calling MS COM object "C++" methods), look at this thing I wrote, use C++ COM objects without any compiler, I had to runtime replace the insides of Win32::API 0.68 to pull it off. | [reply] [d/l] [select] |
by sgv_81 (Novice) on Jul 27, 2012 at 11:20 UTC | |
All tuned in! I've made my tests before reading your last post, and I came to the conclusion that I had to pack myTable as 'L'. Then I've plugged your code in and confirmed it, which is reassuring. This is the final code for anybody that may find it helpful:
If the tables are the same, I get the following results: Note that The returned value of myTableCompare was: 1. Which is fair enough since we've specified that the return type of myTableCompare is numeric:
However if the tables are not equal, the results I get are the following: In this case, The returned value of myTableCompare was: 48168704. Is this expected? Is the boolean defined as 1 if it's True and not 1 (in this case 48168704) if it is False. I would personally have expected a 0 instead. | [reply] [d/l] [select] |
by bulk88 (Priest) on Jul 27, 2012 at 15:24 UTC | |
Put the cdecl thing on. Cdecl should be on for every C function, no exceptions. So far we learned that there are no stdcall functions in your DLL. I explained earlier why myTableCreate wont crash as stdcall even though stdcall is wrong. In your debug code's print messages you call the tables "handles". I dont know if that is correct. Win32 API calls it a HANDLE because "void *" doesnt work with Win32 API. Here is a tool to prove if they are pointers or not This is a wrapper around IsBadReadPtr. IsBadReadPtr will literally tell you if you will access violation/seg fault on any particular pointer from attempting to read that pointer block. All your 48,000,000s tables are probably pointers. What the length of the table memory block in the 48,000,000s? I dont know, maybe you know since you have the docs to your DLL. I can tell you that it is atleast 4 byte long since that is the minimum allocation size, cuz you have a 4 or 8 byte header behind the start of the malloc block that the malloc system puts there for book keeping, to make the pools tidy, the actual allocation is 8 (4 byte header, 4 bytes to you, you asked for 1-4 bytes) or 16 (8 byte header, 8 bytes to you, you asked for 1-8 bytes). Now if you use IsBadReadPtr, either all the table handles are readable, or none of them are readable. 48,000,000 things can really be a GUID/HANDLE/Encrypted pointer/record number/generation counter and not a memory block. Also the 48,000,000 may not 1 for 1 line up with malloc calls. For example, the 48,000,000 pointers might be pointers into 1 malloced block that is an array of all table headers that are live by the DLL, inside the DLL, so you couldn't call free() on then even if you wanted. Remember IsBadReadPtr can not tell the difference between allocated from the OS but free memory, and allocated from the OS and allocated from malloc memory. IsBadReadPtr is just a debugging tool, you dont have to use it. You do things like and but here you did Why not do != 0 instead of > 0, what if its a negative number? (in 0.68 all return/out values are signed, unsigned is ignored and you get signed, thats a bug with 0.68). Yep, the reason for void ** is because the DLL will swap out the table pointer if it internally reallocates the table pointer because the old table pointer didn't meet the DLL's requirements (size, location, etc). It also means you need to be diligent, to not use the old void * (which will crash since its freed/reallocated to something else memory). In this case, The returned value of myTableCompare was: 48168704. Is this expected? Is the boolean defined as 1 if it's True and not 1 (in this case 48168704) if it is False. I would personally have expected a 0 instead.No. Error numbers in unix http://www.ibm.com/developerworks/aix/library/au-errnovariable/ and in Windows, 0 is success http://msdn.microsoft.com/en-us/library/windows/desktop/ms681382%28v=vs.85%29.aspx. BOOL in windows is 0 failed, true. MS headers say 1 is TRUE, and BOOL functions usually return 1, I've never seen a BOOL that returns something other than 1 on success, but everyone tests for true, not == 1, note you have a "bool" not a microsoft "BOOL", and your header file and the prototype is very messed up if it says bool/BOOL and delivers pointers. If the programmer was responsible, there should be symbolic constants somewhere in your header file that say what the non pointer return values/return flags are, and what is the cut off number between table pointers and status codes for myTableCompare. Who wrote this DLL? In terms of special magic return values and pointers, MS DLL that return "HANDLE", either return -1 or 0 on failure (read the docs, some do -1, some do 0, some do both), or a HANDLE. With an unknown function, everything under 2^16 (65536) or 2^12 (4096, 1 page) is not a pointer. In GDI handles, the upper 16 bits is a generation counter to prevent a new handle from being the same as a recently freeded handle, so things that use a freeded handle will fail rather than work erratically on the new handle. The lower 16 bits is the index into an array, see http://msdn.microsoft.com/en-us/library/ms810501.aspx. Kernel handles are different. It should be obvious that myTableCompare is giving you a table */void * to do something with. Since if its "the same" it gives you 1, I will guess 0 is error, and "different but success", you get a table with the delta table. So myTableCompare really returns a myTable, with opaque being 0, 1, or a table. Also I've never seen you free any of the table *s. You will have to do that eventually. Do you have docs or source code for this DLL or only the header file? Download StudPE and look at the export (and if you have time or curiosity, import table) table of that DLL. The PE Export table will show everything you can possibly call in that DLL from C, unless that is a C++ DLL. If its C++ then you have a big problem (virtual tables, etc). The PE export table does not show the prototypes of the functions though. There are ways to reverse engineer and learn the prototypes of the functions if you have the time. I've done it successfully before, since I have some assembly skills. | [reply] [d/l] [select] |