in reply to Re^6: WIN32::API and void* in thread WIN32::API and void*
I think I wasn't clear. On your or your client's 64 bit Windows machine, are you running a 32 bit perl or a 64 bit perl? (I think your 64 bit perl because J returned 8 bytes).
In C header files traditionally, if __stdcall isn't written in the function declaration AFTER the C preprocessor (WINAPI and CALLBACK both become __stdcall), it is a __cdecl. MSVC by default is __cdecl and I assume every other Windows 32bit compiler in the world is. I've never see an actual use of the command line switch used to switch the default from cdecl to stdcall in my life
Try
# Load the function.
my $LoadTableFromFile = new Win32::API("myDll.dll","myTableLoadFromFil
+e", 'PP', 'I', '_cdecl');
At this point, 32 or 64, it doesn't matter, since I am running low on ideas. You must use '_cdecl' exactly that way, a typo in 0.68 means '__cdecl' and 'cdecl' become stdcall.
I am starting to think your DLL has problems and its not a problem with API. Does the DLL actually work if you write C code for it? Googling "ctbl_v2.dll" returned nothing so its something private you have.
Next idea, now I'm shooting in the dark, can you tried changing
my $pathATable = 'C:/Temp/Requests/testTable.TBL';
to
my $pathATable = 'C:\Temp\Requests\testTable.TBL'; #no ""s
?
Another idea, lets assume there are secret members after opaque, change
# pack the table.
my $packedaTable = pack('J',$aTable);
print Dumper($packedaTable);
if(unpack('J',$packedaTable) == $aTable)
{print "I know how to pack this table.\n";}
else
{die "I dont know how to pack this table";}
to
# pack the table.
my $packedaTable = pack('J',$aTable);
print Dumper($packedaTable);
if(unpack('J',$packedaTable) == $aTable)
{print "I know how to pack this table.\n";}
else
{die "I dont know how to pack this table";}
$packedaTable .= "\x00" x 100000000; #100MB allocation
48120353 sounds like a reasonable memory pointer. Hmm, when you say "What I get it's the famous "Segmentation fault (core dumped)".", are you on Windows or on Linux? Windows doesn't have "Segmentation faults" it has "access violations".
The string "Segmentation fault" isn't even in Perl. Assuming your using Windows, have you clicked the "To see what data this error report contains click here" thing and then "view technical information", and looked where the crash happened and if it happened in your private DLL or not?
Re^8: WIN32::API and void*
by sgv_81 (Novice) on Jul 26, 2012 at 08:31 UTC
|
Mission accomplished. It was the "_cdecl". I've included it and tables are loaded perfectly!!!.
I have some doubts about how HANDLE parameters will translate into the non-prototype calls. I've made a test with myTableCreate() and I think I should treat them as 'N' (I print the dumper for both the prototype and the non-prototype and I get $VAR1=48120369 and $VAR1=48120417, which doesn't seem bad). Furthermore, I'm not sure how they'd be packed (if they'd need to) before passing them to an API function as parameters. For instance:
__declspec(dllimport) bool myTableCompare(myTable lhs, myTable rhs, my
+Table* output, unsigned int *count, double relative_tolerance, double
+ absolute_tolerance)
Assuming BOOL=INT, which seems to work fine with the Kernel32 API BOOL Beep(long,long), the above C declaration translate into the following perl call:
my $TableComparer = new Win32::API("myDll.dll","myTableCompare", 'NNPP
+DD','I','_cdecl');
I'm not completely sure, because I get a segmentation fault when I call $TableComparer with the following parameters:
$count = 1;
$pointerToCount=pack('I',$count);
$RelativeTol=0.001;
$AbsTol=1.0;
my $areTheSame=$TableComparer->Call($LeftTable,$RightTable,$packedOutp
+utTable,$pointerToCount, $RelativeTol,$AbsTol);
Note that in this version of the code, I've passed $LeftTable and $RightTable without packing them before. I've tried to pass their J-packed versions but I still get a segmentation fault.
Another doubt I have comes from the unsigned int pointer in the previous example, I have assumed that the signature is 'NNPPDD', and I've created the pointer using pack('I',$count), which I don't know whether it's right.
By the way this is the part of the code that works, in case somebody needs it:
#! /usr/bin/perl
use Win32::API;
# Load the table creator from the dll.
# C signature: __declspec(dllimport) myTable myTableCreate();
# typedef
# struct myTable {
# void* opaque; ///< Opaque pointer to storage
# } myTable;
$pass=1;
my $CreateTable = new Win32::API("myDll.dll","HANDLE myTableCreate()")
+;
if(not defined $CreateTable) {
die "Can't import API myTableCreate(): $!\n";
}
#Create empty tables.
$pass = 1;
if($pass)
{
my $LeftTable = $CreateTable->Call();
my $RightTable = $CreateTable->Call();
my $outputTable = $CreateTable->Call();
# Make sure that the function does return a memory position, and n
+ot a 0.
$pass = $pass && ($LeftTable>0 && $RightTable>0);
if($pass){print("Empty Tables Succesfully Created. Pass code: ".$p
+ass.".\n");};
}
# pack the table.
if($pass)
{
my $packedLeftTable = pack('J',$LeftTable);
my $packedRightTable = pack('J',$RightTable);
my $packedOutputTable = pack('J',$outputTable);
$pass = $pass && (unpack('J',$packedLeftTable) == $LeftTable && un
+pack('J',$packedRightTable) == $RightTable && unpack('J',$packedOutpu
+tTable) == $outputTable);
if($pass){ print("Pack-Unpack round trip completed. Pass code: ".$
+pass."\n");}
}
# Path definition.
my $pathTableLeft = 'C:/Temp/Requests/testTable1.TBL';
my $pathTableRight = 'C:/Temp/Requests/testTable2.TBL';
# Load the function.
# Load the table file loader from the dll.
# Some info about the API function:
# __declspec(dllimport) enum cStatus myTableLoadFromFile(char const* f
+ilename, myTable* raw_result);
# enum cStatus will treated as an int and interpreted using the array
+@DllTableStatus.
my $LoadTableFromFile = new Win32::API("myDll.dll","myTableLoadFromFil
+e", 'PP', 'I','_cdecl');
if(not defined $LoadTableFromFile) {
die "Can't import API myTableLoadFromFile(): $!\n";
}
if($pass)
{
my @DllTblStatus = ("OK Status, no errors", "Failed to allocate me
+mory", "Unable to open or save file", "Unable to convert value to req
+uested type", "Unknown error", "Validation Failed", "Cell could not b
+e found");
my $isLoadedLeft = $LoadTableFromFile->Call($pathTableLeft,$packed
+LeftTable);
my $isLoadedRight = $LoadTableFromFile->Call($pathTableRight, $pac
+kedRightTable);
$pass = $pass && ($isLoadedLeft==0 && $isLoadedRight==0);
if($pass)
{print("Tables: ".$pathTableLeft." and ".$pathTableRight." loa
+ded correctly. Pass code: ".$pass."\n");}
else
{
if($isLoadedLeft>0){print("Loading table error on ".$pathTable
+Left.": ".@DllTblStatus[$isLoadedLeft]."\n");}
if($isLoadedRight>0){print("Loading table error on ".$pathTabl
+eRight.": ".@DllTblStatus[$isLoadedRight]."\n");}
}
}
PS: I'm using Windows and Cygwin, probably that's why sometimes things look a little bit MS-like and others a little bit Unix-like... | [reply] [Watch: Dir/Any] [d/l] [select] |
|
Mission accomplished. It was the
"_cdecl". I've included it and tables are loaded perfectly!!!.
Good to know it wasnt a Win32::API bug or a bug in your DLL. I am
very confused, since your pack 'J' (Perl Internal Scalar Unsigned
Value) letter is 64 bits long, yet you have a x86-32 DLL and a
x86-32 Perl. Do you have one of the freak Perl builds with native 64
bit integers, but 32 bit pointers running 32 bit assembly code? I will
assume that for the rest of this post.
I have some doubts about how HANDLE
parameters will translate into the non-prototype calls. I've made a
test with myTableCreate() and I think I should treat them as 'N' (I
print the dumper for both the prototype and the non-prototype and I get
$VAR1=48120369 and $VAR1=48120417, which doesn't seem bad).
Furthermore, I'm not sure how they'd be packed (if they'd need to)
before passing them to an API function as parameters.
Win32::API's letter codes are "inspired by" but ARE NOT the same
letters as for pack. 'N' for Win32::API means pointer sized number. For
pack, well I thought you should be using J, since that is normally 4
bytes on 32 bit and 8 bytes on 64 bits, but for your machine, J isn't
the right letter. For myTable struct, it "worked" but J was sorta a
bug/bad choice. The last 4 "\x00" are ignored by your DLL, and the
myTable "struct" you gave is actually 2 pointers long (8 bytes), but
the DLL doesn't know and doesn't care (a property of little endian
numbers). You shouldn't use J with pack for pointers in multimember
structs non-stock Perl build. You need to find the appropriate letter,
see pack.
For instance:
__declspec(dllimport) bool myTableCompare(myTable lhs, myTable rhs, my +Table* output, unsigned int *count, double relative_tolerance, double + absolute_tolerance)
Assuming BOOL=INT, which seems to work
fine with the Kernel32 API BOOL Beep(long,long), the above C
declaration translate into the following perl call:
my $TableComparer = new Win32::API("myDll.dll","myTableCompare", 'NNPP
+DD','I','_cdecl');
I'm not completely sure, because I get
a segmentation fault when I call $TableComparer with the following
parameters:
$count = 1; $pointerToCount=pack('I',$count); $RelativeTol=0.001; $AbsTol=1.0; my $areTheSame=$TableComparer->Call($LeftTable,$RightTable,$packedOutp +utTable,$pointerToCount, $RelativeTol,$AbsTol);
Note that in this version of the code,
I've passed $LeftTable and $RightTable without packing them before.
I've tried to pass their J-packed versions but I still get a
segmentation fault.
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.
Another doubt I have comes from the
unsigned int pointer in the previous example, I have assumed that the
signature is 'NNPPDD', and I've created the pointer using
pack('I',$count), which I don't know whether it's right.
Correct. Any 'P' letters must be "ab\x01\x02cd" strings. Never ever
123.
PS: I'm using Windows and Cygwin,
probably that's why sometimes things look a little bit MS-like and
others a little bit Unix-like...
90% of my knowledge is Visual C or ActivePerl, 10% Mingw or
Strawberry. 0% cygwin. I dont have a cygwin perl installed. Seg fault
sounds correct for Cygwin Perl, since Cygwin Perl thinks and acts like
Linux.
Can you do a print Dumper on all the parameters in "my $areTheSame=$TableComparer->Call($LeftTable,$RightTable,$packedOutputTable,$pointerToCount, $RelativeTol,$AbsTol);" before you do the Call() that crashes?
| [reply] [Watch: Dir/Any] |
|
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:
my $outputTable = $CreateTable->Call();
my $packedOutputTable = pack('J',$outputTable);
I understand that's the right way to pass a void**.
| [reply] [Watch: Dir/Any] [d/l] |
|
|
|
|
|