Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

Re^7: WIN32::API and void*

by bulk88 (Priest)
on Jul 25, 2012 at 20:52 UTC ( [id://983738]=note: print w/replies, xml ) Need Help??


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?

Replies are listed 'Best First'.
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...

      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?

        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**.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://983738]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (7)
As of 2024-03-28 08:08 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found