http://qs1969.pair.com?node_id=234310

chinman has asked for the wisdom of the Perl Monks concerning the following question:

Purveyors of Perl Wisdom,

I'm trying to access a Win32 DLL using the Win32 OLE module. Some test code is shown below.

#!/usr/bin/perl -w #xcalibur automation test script use strict; use Win32::OLE; use Win32::OLE::Const 'XRawfile2 1.0 Type Library'; #specify a data file and create the object my $rawFile = 'C:\Xcalibur\Data\oligo01.raw'; my $XRawfile = new Win32::OLE('Xrawfile.XRawfile.1') or die "yikes, ca +n't instantiate object\n"; #read back the object my $obj = Win32::OLE->QueryObjectType($XRawfile); #this line returns "IXRawfile", everything appears ok print "object type = $obj\n"; #open a file into the XRawfile object $XRawfile->Open("$rawFile"); #this line seems to indicate everything is ok as it doesn't return an +error test_for_error(); #try to readback the file we just loaded #alas this appears to suck pond water - doesn't work my $filename = ""; $XRawfile->GetFileName($filename); test_for_error(); print "the file is: $filename\n"; #sub that prints an error if encountered sub test_for_error { my $error = Win32::OLE->LastError(); print $error if $error; }

Basically, it looks like I can create the object ok (line 15). I also think that I'm opening the rawfile ok (line 23), since no errors are returned. I can't seem to get the other methods to work. I think, the problem is that the other methods associated with this DLL require the variables to be pointers. For example, the GetFileName method that I've attempted to implement above actually appears to require a pointer to a string. For example, the function call from the OLEview for the GetFileName method is:

void GetFileName(BSTR* pbstrFileName);

Is there a way to implement these calls with Win32::OLE, or do I need to use the Win32::API or Win32::API::Prototype? Some of the other methods require pointers to longs, doubles, or variants. Any thoughts (or pointers) would be greatly appreciated.

Regards,
chinman

Replies are listed 'Best First'.
Re: "pointers" for calling a DLL
by Solo (Deacon) on Feb 11, 2003 at 04:05 UTC
    use Win32::OLE::Variant; # ... my $filename = Variant(VT_BSTR|VT_BYREF, 0); $XRawfile->GetFileName($filename);
    More details can be found near the bottom of Win32::OLE::Variant's POD.
    --
    You said you wanted to be around when I made a mistake; well, this could be it, sweetheart.
Re: "pointers" for calling a DLL
by Nitrox (Chaplain) on Feb 11, 2003 at 03:55 UTC
    I think you want:
    $filename = $XRawfile->GetFileName();
    Also, you can use Win32::OLE::Variant() to force the datatype but I've never had to do this, Win32::OLE has been pretty good about converting them.

    -Nitrox

Re: "pointers" for calling a DLL
by chinman (Monk) on Feb 11, 2003 at 04:42 UTC
    Solo

    This looks like it should work, but I've still got no joy. If I print the filename, it's still coming back as "0". Should I have to do anything to coerce $filename back into something that I can print? I'm wondering if the "Open" method is working in the first place.

    UPDATE:

    It looks like I can get methods that want a pointer to a long to work by initializing them with $var = Variant(VT_I4|VT_BYREF, 0);. The docs say that the BSTR variables have to be initialized to NULL. Isn't that what we're doing with the $var = Variant(VT_BSTR|VT_EMPTY, 0) statment?

    chinman

      Variant BSTRs should automatically print nicely.

      You say you found GetFileName in OLE View, but was it of type "Dispinterface" or something else? Do you have an automation/scripting object model for the component--or can you get one?

      COM/OLE components can contain interfaces that only C/C++ can hit. And they often contain thin wrappers, called Dispinterfaces, around these C/C++ calls that VB, vbs, Perl, et al can easily use. You may have found the wrong one. I wonder if the syntax is going to be something different... for instance:

      my $filename = $XRawFile->{Filename};

      ** /me shrugs ** But this is just a hunch.

      --
      Never tell me the odds!
Re: "pointers" for calling a DLL
by tachyon (Chancellor) on Feb 11, 2003 at 08:12 UTC

    When you Open a new file (using your application object) you may create a new file object so perhaps you need to do something like this?

    my $obj = $XRawfile->Open("$rawFile"); my $filename = $obj->GetFileName(); print "the file is: $filename\n";

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: "pointers" for calling a DLL
by chinman (Monk) on Feb 11, 2003 at 04:03 UTC
    Nitrox,

    I wish it was that easy
    $filename = $XRawfile->GetFileName();
    The above does not work. The method is supposed to return the result into the pointer variable thingy. That's the odd thing about this DLL.

Re: "pointers" for calling a DLL
by chinman (Monk) on Feb 11, 2003 at 13:37 UTC
    Hey, thanks to everyone for your help so far...I think I'm almost there. I can get the methods that reference either longs or doubles to work.

    I'm still having problems with any method requires a pointer to a string. I am referring to the usage under the dispinterface IXRawfile in the OLEview. For the GetFileName method it is:

    [id(0x00000003), helpstring("method GetFileName")] void GetFileName(BSTR* pbstrFileName);

    Now if I look in the user documentation for the library it says that "the pbstrFileName variable is a valid pointer to a BSTR variable. This variable must exist and be initialized to NULL." My question is, does this bit of code initialize this variable to NULL? I can't see any reason why this should not work...dang.

    my $filename = Variant(VT_BSTR|VT_BYREF, 0);

    Thanks, chinman

      The manual says:

      my $filename = Variant(VT_BSTR|VT_BYREF, VT_NULL);
      --
      Without precise calculations we could fly right through a star or bounce too close to a supernova and that'd end your trip real quick, wouldn't it?

Re: "pointers" for calling a DLL
by chinman (Monk) on Feb 11, 2003 at 14:08 UTC
    ok, maybe we're getting somewhere, but

    my $filename = Variant(VT_BSTR|VT_BYREF, VT_NULL);

    is returning "1" for $filename when it was returning "0" before.

    UPDATE: I don't know if this helps but, I tested this out in VB (I know, I know, yuk...). In order to get this library to work, I had to use the "Call" function on the GetFileName method. Here's the VB code.

    Dim rawfile As XrawFile Set rawfile = New XrawFile filename = "C:\Program Files\ProMassXcali\TestData\oligos\oligo01.raw" rawfile.Open (filename) Dim return_filename As String Call rawfile.GetFileName(return_filename) MsgBox return_filename

    Any other clues about how I could get this to work under Win32::OLE?

    thanks, chinman

Re: "pointers" for calling a DLL
by chinman (Monk) on Feb 16, 2003 at 01:59 UTC
    Ok, I finally got it to work. You have to leave out the DATA parameter in the Variant method.

    For example, this does not work:

    my $var = Variant(VT_BSTR|VT_BYREF, 0);

    but, this does:

    my $var = Variant(VT_BSTR|VT_BYREF);

    FINALLY!!!

      Thanks for posting your solution!
      --
      Now let's blow this thing and go home!