Problem with Win32::API and pointers

Problem with Win32::API and pointers

am 12.05.2006 16:02:29 von jrgoody

Hi,

I'm working on a project and trying to use the Win32::API to call a
DLL from Perl, but I have some problems. I'm using the last version
of the API (0.41).

I'll describe my problem. I hope someone can help me. The DLL I've
been trying to call from Perl is the FTD2XX.dll from FTDI, a Library to
communicate with a chip connected to the computer via USB. The thing is
really simple, this is my code:

#CODE
STARTS****************************************************** ************************
use Win32::API;

Win32::API::Type->typedef( 'FT_HANDLE', 'PVOID' );
Win32::API::Type->typedef( 'FT_STATUS', 'ULONG' );

#FT_Open
Win32::API->Import( 'FTD2XX', 'FT_STATUS FT_Open(int
deviceNumber,FT_HANDLE *pHandle)' );

#FT_Close
Win32::API->Import( 'FTD2XX', 'FT_STATUS FT_Close(FT_HANDLE ftHandle)'
);


#Open port
FT_Open(0,$ft_handle);

#Close port
$ft_status = FT_Close($$ft_handle);
#CODE
ENDS******************************************************** ***************************

This is how the functions and variables are defined in the .h file:

....
typedef PVOID FT_HANDLE;
typedef ULONG FT_STATUS;
....

FTD2XX_API
FT_STATUS WINAPI FT_Open(
int deviceNumber,
FT_HANDLE *pHandle
);

....
FTD2XX_API
FT_STATUS WINAPI FT_Close(
FT_HANDLE ftHandle
);
....


The function FT_Open should return FT_STATUS (this works) but also a
pointer *pHandle to the Handle, which is to be used for the forthcoming
operations to the port, like in the function FT_Close.

But when I run the program, this is what I receive:

"Perl Command Line Interpreter has encountered a problem and needs to
close. We are sorry for the inconvenience."

The problem is on the FT_Close function. If I comment it out, the
program runs OK (FT_Open returns Status OK), so I'm pretty sure the
problem has something to do with the handle. As I said, FT_Open should
give a pointer to the handle (2nd argument) and the handle itself is to
be used in FT_Close (only argument).

I thing it should work with the API, because it is pretty much the same
as in one of the examples in the API Documentation. But I can't get
it to work. Someone sees an error or something missing in my code?
Please tell me if you need more info from me or if you have any
suggestions on how I can fix this. This is really important for me. I
thank you very much in advance.

Re: Problem with Win32::API and pointers

am 12.05.2006 17:25:04 von Thomas Kratz

jrgoody@googlemail.com wrote:
> Hi,
>
> I'm working on a project and trying to use the Win32::API to call a
> DLL from Perl, but I have some problems. I'm using the last version
> of the API (0.41).
>
> I'll describe my problem. I hope someone can help me. The DLL I've
> been trying to call from Perl is the FTD2XX.dll from FTDI, a Library to
> communicate with a chip connected to the computer via USB. The thing is
> really simple, this is my code:
>
> #CODE
> STARTS****************************************************** ************************
> use Win32::API;
>
> Win32::API::Type->typedef( 'FT_HANDLE', 'PVOID' );
> Win32::API::Type->typedef( 'FT_STATUS', 'ULONG' );
>
> #FT_Open
> Win32::API->Import( 'FTD2XX', 'FT_STATUS FT_Open(int
> deviceNumber,FT_HANDLE *pHandle)' );
>
> #FT_Close
> Win32::API->Import( 'FTD2XX', 'FT_STATUS FT_Close(FT_HANDLE ftHandle)'
> );
>
>
> #Open port
> FT_Open(0,$ft_handle);
>
> #Close port
> $ft_status = FT_Close($$ft_handle);

This looks wrong. You are treating $ft_handle like a reference to a perl
scalar. But it contains the address of a void pointer.

I think you have to dereference the pointer in $ft_handle, but I have no
idea how to accomplish this with Win32::API. I googled for it, but nothing
helpful came up.

Thomas

--
$/=$,,$_=,s,(.*),$1,see;__END__
s,^(.*\043),,mg,@_=map{[split'']}split;{#>J~.>_an~>>e~...... >r~
$_=$_[$%][$"];y,<~>^,-++-,?{$/=--$|?'"':#..u.t.^.o.P.r.>ha~.e..
'%',s,(.),\$$/$1=1,,$;=$_}:/\w/?{y,_, ,,#..>s^~ht<._..._..c....
print}:y,.,,||last,,,,,,$_=$;;eval,redo}#.....>.e.r^.>l^..>k ^.-

Re: Problem with Win32::API and pointers

am 12.05.2006 19:53:42 von unknown

Thomas Kratz wrote:
> jrgoody@googlemail.com wrote:
>
>> Hi,
>>
>> I'm working on a project and trying to use the Win32::API to call a
>> DLL from Perl, but I have some problems. I'm using the last version
>> of the API (0.41).
>>
>> I'll describe my problem. I hope someone can help me. The DLL I've
>> been trying to call from Perl is the FTD2XX.dll from FTDI, a Library to
>> communicate with a chip connected to the computer via USB. The thing is
>> really simple, this is my code:
>>
>> #CODE
>> STARTS****************************************************** ************************
>>
>> use Win32::API;
>>
>> Win32::API::Type->typedef( 'FT_HANDLE', 'PVOID' );
>> Win32::API::Type->typedef( 'FT_STATUS', 'ULONG' );
>>
>> #FT_Open
>> Win32::API->Import( 'FTD2XX', 'FT_STATUS FT_Open(int
>> deviceNumber,FT_HANDLE *pHandle)' );
>>
>> #FT_Close
>> Win32::API->Import( 'FTD2XX', 'FT_STATUS FT_Close(FT_HANDLE ftHandle)'
>> );
>>
>>
>> #Open port
>> FT_Open(0,$ft_handle);
>>
>> #Close port
>> $ft_status = FT_Close($$ft_handle);
>
>
> This looks wrong. You are treating $ft_handle like a reference to a perl
> scalar. But it contains the address of a void pointer.
>
> I think you have to dereference the pointer in $ft_handle, but I have no
> idea how to accomplish this with Win32::API. I googled for it, but
> nothing helpful came up.
>
> Thomas
>

I agree with Thomas -- a Perl dereference is not what is needed here.

It has been a while since I messed with this sort of thing, but you
might want to try something like the following:

# >>>> begin code fragment

# Open port
$ft_handle = ' '; # Preallocate 4 bytes.
FT_Open (0, $ft_handle);

# Dereference handle
$ft_handle = unpack ('L', $ft_handle);

# Close port
$ft_status = FT_Close ($ft_handle);

# >>>> end code fragment

This is based on some code I wrote a while back, which uses the older

$obj = Win32::API->new (dll, entrypoint, [argument ...], return)

syntax. I do not know that you need to switch to this syntax to use the
"preallocate before, unpack after" technique. I also do not know the
current state of Aldo Calpini's documentation, but I do recall
considerable code bashing to figure out what worked.

Tom Wyant

Re: Problem with Win32::API and pointers

am 15.05.2006 12:11:36 von jrgoody

Thank you all for your responses.

I've tried Tom's suggestions, but I still have the same problem.

I receive the same Windows message "Perl Command Line Interpreter has
encountered a problem and needs to close. We are sorry for the
inconvenience.", but this time here:

$ft_handle = unpack ('L',$ft_handle);

So it looks like it occurs the first time $ft_handle is used as
argument to a function.

I tried to print the following in different places (for debugging):
print ".$ft_handle."; with the following results:

At the beginning of the code: ..
After $ft_handle = ' '; :
.. .
After $ft_status = $ft_open->Call(0,$ft_handle); : ..
After $ft_handle = unpack ('L',$ft_handle); : Nothing,

the program doesn't returns after calling unpack(). Any suggestions?
Need more info? Should I try something else?

Thanks a lot in advance.

Re: Problem with Win32::API and pointers

am 15.05.2006 16:30:45 von Thomas Kratz

jrgoody@googlemail.com wrote:
> Thank you all for your responses.
>
> I've tried Tom's suggestions, but I still have the same problem.
>
> I receive the same Windows message "Perl Command Line Interpreter has
> encountered a problem and needs to close. We are sorry for the
> inconvenience.", but this time here:
>
> $ft_handle = unpack ('L',$ft_handle);
>
> So it looks like it occurs the first time $ft_handle is used as
> argument to a function.
>
> I tried to print the following in different places (for debugging):
> print ".$ft_handle."; with the following results:
>
> At the beginning of the code: ..
> After $ft_handle = ' '; :
> . .
> After $ft_status = $ft_open->Call(0,$ft_handle); : ..
> After $ft_handle = unpack ('L',$ft_handle); : Nothing,
>
> the program doesn't returns after calling unpack(). Any suggestions?
> Need more info? Should I try something else?

Did you check that $ft_status reports a successful call to FT_OPEN?

Perhaps someone at perlmonks (http://perlmonks.org) or better still the
perl-win32-users mailing list at ActiveState has better ideas. If you are
very lucky, Aldo will still be reading the latter.

Thomas

--
$/=$,,$_=,s,(.*),$1,see;__END__
s,^(.*\043),,mg,@_=map{[split'']}split;{#>J~.>_an~>>e~...... >r~
$_=$_[$%][$"];y,<~>^,-++-,?{$/=--$|?'"':#..u.t.^.o.P.r.>ha~.e..
'%',s,(.),\$$/$1=1,,$;=$_}:/\w/?{y,_, ,,#..>s^~ht<._..._..c....
print}:y,.,,||last,,,,,,$_=$;;eval,redo}#.....>.e.r^.>l^..>k ^.-

Re: Problem with Win32::API and pointers

am 16.05.2006 11:45:51 von jrgoody

Well, thank you all. It works now!

First of all, Tom's suggestions were right. It didn't work at the
beginning because although I preallocated the memory for the reference
and dereferenced the handle after the function call, as Tom explained,
I was still using the new Win32::API syntax to import a function, using
the intact C prototype.

As I found out later, I had to use the "old" and "deprecated" method
for importing a function, using the parameter list. These are excerpts
of my (working) code:

# begin code fragment

use Win32::API;

#FT_Open
#Prototype: FT_STATUS WINAPI FT_Open( int deviceNumber, FT_HANDLE
*pHandle);
$ft_open = Win32::API->new('FTD2XX', FT_Open, 'NP', 'N');

#FT_Close
#Prototype: FT_STATUS WINAPI FT_Close( FT_HANDLE ftHandle );
$ft_close = Win32::API->new('FTD2XX', FT_Close, 'N', 'N');


#Open port
$ft_handle_p = ' '; #Preallocate 4 bytes
$ft_status = $ft_open->Call(0,$ft_handle_p);

$ft_handle = unpack ('L',$ft_handle_p); #Dereference handle

#Close port
$ft_status = $ft_close->Call($ft_handle);

# end code fragment

Another interesting thing (and I think the cause of the problems using
directly the C prototype when importing the function) is that if you
look at the function prototypes, *pHandle (in FT_Open) and ftHandle (in
FT_Close) are both declared as of type FT_HANDLE, which is defined in
the header file as PVOID. However, in the case of FT_Open the function
returns a pointer to the handle, while FT_Close expects the handle
itself. So, in the parameter list of FT_Close you must have an 'N'
(unsigned long) and not a 'P' (pointer), even if the fthandle is also
a PVOID in the C declaration.

Well, I hope this helps also, and again thanks a lot for the fast and
very effective help!

Re: Problem with Win32::API and pointers

am 16.05.2006 17:02:23 von unknown

jrgoody@googlemail.com wrote:
> Well, thank you all. It works now!
>
> First of all, Tom's suggestions were right. It didn't work at the
> beginning because although I preallocated the memory for the reference
> and dereferenced the handle after the function call, as Tom explained,
> I was still using the new Win32::API syntax to import a function, using
> the intact C prototype.
>
> As I found out later, I had to use the "old" and "deprecated" method
> for importing a function, using the parameter list.

I do not know that you "have" to use the old method - I just couldn't
figure out how to use the new method. If someone knows how to do it the
new way, I would love to see it.

Glad to help.

Tom Wyant