Interfacing with Matlab using Win32::OLE

Discussion in 'Perl Misc' started by scottmf, Jul 14, 2006.

  1. scottmf

    scottmf Guest

    I am not sure if this is more of an issue with Matlab or Perl, but here
    is what I am having trouble doing:
    I want a user to be able to start Matlab (on a WinXP machine) and run a
    matlab program like perl_link.m below that runs a perl script. The
    perl script then parses a large data file and stores the results in
    several arrays in matlab using OLE objects. The rest of the matlab
    program then processes those arrays. I have been able to get the
    perl->matlab OLE interface work if I start matlab from within the perl
    script using

    $ML = Win32::OLE->new('Matlab.Application', sub {$_[0]->Quit;})
    or die "Oops, cannot start MATLAB";

    But I cannot find the matlab OLE object if I start matlab first and run
    the perl script from inside matlab.

    This is the kind of output I would expect to see from running the
    matlab program:

    # Object=Win32::OLE=HASH(0x183ef90) Class=DIMLApp
    Found 1 OLE Object(s)

    Instead I don't fine any OLE objects. Any suggestions or additional
    documentation I haven't yet found would be very helpful.

    Here are the matlab and perl files I am using:

    Perl_link.m:

    function perl_link
    %

    %% would like to use test.pl to parse some large data file and store
    the
    %% information in arrays in matlab

    !perl test.pl

    %% Would then like to use matlab to do some processing on the arrays
    and
    %% plot the results

    Test.pl:

    #!/usr/bin/perl -w
    #
    use strict;
    use warnings;
    use Win32::OLE;
    use Win32::OLE::Variant;

    my $Count;
    $Count = Win32::OLE->EnumAllObjects(sub {
    my $Object = shift;
    my $Class = Win32::OLE->QueryObjectType($Object);
    printf "# Object=%s Class=%s\n", $Object, $Class;
    });
    print "Found $Count OLE Object(s)\n";
    scottmf, Jul 14, 2006
    #1
    1. Advertising

  2. scottmf

    Ben Morrow Guest

    Quoth "scottmf" <>:
    > I am not sure if this is more of an issue with Matlab or Perl, but here
    > is what I am having trouble doing:
    > I want a user to be able to start Matlab (on a WinXP machine) and run a
    > matlab program like perl_link.m below that runs a perl script. The
    > perl script then parses a large data file and stores the results in
    > several arrays in matlab using OLE objects. The rest of the matlab
    > program then processes those arrays. I have been able to get the
    > perl->matlab OLE interface work if I start matlab from within the perl
    > script using
    >
    > $ML = Win32::OLE->new('Matlab.Application', sub {$_[0]->Quit;})
    > or die "Oops, cannot start MATLAB";
    >
    > But I cannot find the matlab OLE object if I start matlab first and run
    > the perl script from inside matlab.
    >

    <perl script run from within matlab>
    > #!/usr/bin/perl -w
    > #
    > use strict;
    > use warnings;
    > use Win32::OLE;
    > use Win32::OLE::Variant;
    >
    > my $Count;
    > $Count = Win32::OLE->EnumAllObjects(sub {
    > my $Object = shift;
    > my $Class = Win32::OLE->QueryObjectType($Object);
    > printf "# Object=%s Class=%s\n", $Object, $Class;
    > });
    > print "Found $Count OLE Object(s)\n";


    I'm fairly sure you still need the Win32::OLE->new line. If matlab is
    running it should give you a handle on the current instance. [Caveat: my
    understanding of OLE is sketchy at best :)]

    The Perl program is in no sense 'inside' matlab. It is a completely
    separate process: it doesn't even know you invoked it from matlab, so
    how would you get an OLE object?

    As Sinan said, it may be easier not to bother with OLE. Does matlab have
    a function to import, say, a CSV file? I would probably start along that
    route: write a CSV file with the data you want in Perl, and then import
    it into matlab from the matlab macro.

    Ben

    --
    Razors pain you / Rivers are damp
    Acids stain you / And drugs cause cramp. [Dorothy Parker]
    Guns aren't lawful / Nooses give
    Gas smells awful / You might as well live.
    Ben Morrow, Jul 14, 2006
    #2
    1. Advertising

  3. scottmf

    scottmf Guest

    > I'm fairly sure you still need the Win32::OLE->new line. If matlab is
    > running it should give you a handle on the current instance. [Caveat: my
    > understanding of OLE is sketchy at best :)]
    >
    > The Perl program is in no sense 'inside' matlab. It is a completely
    > separate process: it doesn't even know you invoked it from matlab, so
    > how would you get an OLE object?


    when I use the Win32::OLE->new line it launches a new instance of
    matlab rather than linking to the current instance. I think this is
    the basic problem; that I need some way to link the perl script to the
    current matlab instance.

    > As Sinan said, it may be easier not to bother with OLE. Does matlab have
    > a function to import, say, a CSV file? I would probably start along that
    > route: write a CSV file with the data you want in Perl, and then import
    > it into matlab from the matlab macro.


    Matlab does have a csv inport function, and this process would work,
    but it seems like there is some way to link the two that I just haven't
    found yet. I perfer to avoid writing and then deleting temp files when
    it is not absolutely necessary...

    Thanks for the suggestions
    ~Scott
    scottmf, Jul 15, 2006
    #3
  4. scottmf

    Ben Morrow Guest

    Quoth "scottmf" <>:
    > > I'm fairly sure you still need the Win32::OLE->new line. If matlab is
    > > running it should give you a handle on the current instance. [Caveat: my
    > > understanding of OLE is sketchy at best :)]
    > >
    > > The Perl program is in no sense 'inside' matlab. It is a completely
    > > separate process: it doesn't even know you invoked it from matlab, so
    > > how would you get an OLE object?

    >
    > when I use the Win32::OLE->new line it launches a new instance of
    > matlab rather than linking to the current instance. I think this is
    > the basic problem; that I need some way to link the perl script to the
    > current matlab instance.


    OK, you are reading the Win32::OLE docs, yes? About 30 seconds worth of
    reading suggests to me that

    my $ML = Win32::OLE->GetActiveObject('Matlab.Application')
    or die "Matlab not running";

    is what you want. Is this wrong?

    > > As Sinan said, it may be easier not to bother with OLE. Does matlab have
    > > a function to import, say, a CSV file? I would probably start along that
    > > route: write a CSV file with the data you want in Perl, and then import
    > > it into matlab from the matlab macro.

    >
    > Matlab does have a csv inport function, and this process would work,
    > but it seems like there is some way to link the two that I just haven't
    > found yet. I perfer to avoid writing and then deleting temp files when
    > it is not absolutely necessary...


    In general I'd agree, but... OLE is messy. Can you open a pipe to perl,
    and read CSV from it?

    Ben

    --
    Razors pain you / Rivers are damp
    Acids stain you / And drugs cause cramp. [Dorothy Parker]
    Guns aren't lawful / Nooses give
    Gas smells awful / You might as well live.
    Ben Morrow, Jul 15, 2006
    #4
  5. scottmf

    Ben Morrow Guest

    Quoth "A. Sinan Unur" <>:
    > Ben Morrow <> wrote in
    > news::
    >
    > >
    > > Quoth "scottmf" <>:
    > >> > I'm fairly sure you still need the Win32::OLE->new line. If matlab
    > >> > is running it should give you a handle on the current instance.
    > >> > [Caveat: my understanding of OLE is sketchy at best :)]
    > >> >
    > >> > The Perl program is in no sense 'inside' matlab. It is a completely
    > >> > separate process: it doesn't even know you invoked it from matlab,
    > >> > so how would you get an OLE object?
    > >>
    > >> when I use the Win32::OLE->new line it launches a new instance of
    > >> matlab rather than linking to the current instance. I think this is
    > >> the basic problem; that I need some way to link the perl script to
    > >> the current matlab instance.

    > >
    > > OK, you are reading the Win32::OLE docs, yes? About 30 seconds worth
    > > of reading suggests to me that
    > >
    > > my $ML = Win32::OLE->GetActiveObject('Matlab.Application')
    > > or die "Matlab not running";
    > >
    > > is what you want. Is this wrong?

    >
    > He wants a _specific_ instance of MatLab. That is:
    >
    > * Invoke MatLab script in MatLab
    > * MatLab script invokes Perl script
    > * Perl script somehow finds a handle to the instance of
    > MatLab that invoked it
    >
    > Now, I don't know if it applies here, but I found out the hard way
    > that one cannot really do that with Excel:
    >
    > http://groups.google.com/group/comp..._frm/thread/3813460c5c0095d2/9d86615b61068685


    OK... again, my knowledge of COM+ is not good, but...

    Firstly, in the common case that there is only one instance of matlab
    running then GetActiveObject will do the right thing.

    If you don't trust that, then as far as I can understand from OLE.xs and
    MSDN

    my $ml_file = $ARGV[0];
    my $ML = Win32::OLE->GetObject($ml_file)
    or die "can't get a handle on '$ml_file'";

    should allow you to invoke Perl passing it the current filename, and
    will use the currently open instance of that file, if any, or open it in
    a currently running matlab, if any, or create a new matlab editing that
    file. That is, it gets a handle on that file somehow; and I'm *pretty*
    sure that if you have it opened and unsaved you get that instance rather
    than a new instance from the file. Try it and see (I can't, having
    neither matlab nor win32 :) ).

    > Starting a Dedicated Server
    >
    > To specify a dedicated server, use the ProgID, matlab.application.single,
    > (or the version-specific ProgID, matlab.application.single.N).
    >
    > Each client that requests a connection to MATLAB using a dedicated ProgID
    > creates a separate instance of MATLAB, and that server will not be shared
    > with any other client. Therefore, there can be several instances of a
    > dedicated server running simultaneously, since the dedicated server is
    > not shared by multiple clients.
    >
    > Now, this opens some possibilities.


    Err... I don't think so. The OP explicitly wants to connect to *a
    currently running* matlab instance, whereas this guarantees to start a
    new one.

    > A simple:
    >
    > result = perl('do_something.pl', 'input.data', 'output.m');
    >
    > would suit my tastes more. Besides, this would enable your program
    > to be used on other OS's as well.


    Yes.

    Ben

    --
    Heracles: Vulture! Here's a titbit for you / A few dried molecules of the gall
    From the liver of a friend of yours. / Excuse the arrow but I have no spoon.
    (Ted Hughes, [ Heracles shoots Vulture with arrow. Vulture bursts into ]
    'Alcestis') [ flame, and falls out of sight. ]
    Ben Morrow, Jul 15, 2006
    #5
  6. scottmf

    scottmf Guest

    > OK... again, my knowledge of COM+ is not good, but...
    >
    > Firstly, in the common case that there is only one instance of matlab
    > running then GetActiveObject will do the right thing.
    >
    > If you don't trust that, then as far as I can understand from OLE.xs and
    > MSDN
    >
    > my $ml_file = $ARGV[0];
    > my $ML = Win32::OLE->GetObject($ml_file)
    > or die "can't get a handle on '$ml_file'";
    >
    > should allow you to invoke Perl passing it the current filename, and
    > will use the currently open instance of that file, if any, or open it in
    > a currently running matlab, if any, or create a new matlab editing that
    > file. That is, it gets a handle on that file somehow; and I'm *pretty*
    > sure that if you have it opened and unsaved you get that instance rather
    > than a new instance from the file. Try it and see (I can't, having
    > neither matlab nor win32 :) ).


    I tried using MS Excel to check and see if it functions differently
    from Matlab and found that if I have an Excel file open

    my $Count;
    $Count = Win32::OLE->EnumAllObjects(sub {
    my $Object = shift;
    my $Class = Win32::OLE->QueryObjectType($Object);
    printf "# Object=%s Class=%s\n", $Object, $Class;
    });
    print "Found $Count OLE Object(s)\n";

    Still finds no OLE objects

    but:

    my $file = "C:\\MATLAB6p5\\work\\Book1.xls";
    my $ML = Win32::OLE->GetObject($file)
    or print "can't get a handle on '$file'";
    print "$ML\n";

    Finds the OLE object just fine!! I'm not sure why passing the filename
    specifically allows it to find the object, but asking for a listing of
    all OLE objects using EnumAllObjects does not work??

    As far as Matlab goes, if I have my perl_link.m file open in the matlab
    program editor (just a text editor in matlab), or if I run perl_link.m
    in matlab, and this runs my perl script:

    my $Count;
    $Count = Win32::OLE->EnumAllObjects(sub {
    my $Object = shift;
    my $Class = Win32::OLE->QueryObjectType($Object);
    printf "# Object=%s Class=%s\n", $Object, $Class;
    });
    print "Found $Count OLE Object(s)\n";

    finds 0 OLE objects (the same as with MS Excel), but unlike excel:

    my $file = "C:\\MATLAB6p5\\work\\perl_link.m";
    my $ML = Win32::OLE->GetObject($file)
    or print "can't get a handle on '$file'\n";

    Returns the following:

    Win32::OLE(0.1601) error 0x800401e6: "Bad extension for file" at
    test.pl line 22
    eval {...} called at test.pl line 22
    can't get a handle on 'C:\MATLAB6p5\work\perl_link.m'

    I'm not sure exactly what this error is, or why ".m" is a "bad
    extension for file". I'm wondering (Not knowing much about OLE) if
    there is some way for a program to start without this turned on, and
    that is why perl is not finding the active instance of matlab??

    Any other suggestions on ways I might be able to go about doing this
    before I go ahead and try temp files??

    Thanks,
    ~Scott
    scottmf, Jul 17, 2006
    #6
  7. scottmf

    Ben Morrow Guest

    Quoth "scottmf" <>:
    > > OK... again, my knowledge of COM+ is not good, but...
    > >
    > > Firstly, in the common case that there is only one instance of matlab
    > > running then GetActiveObject will do the right thing.
    > >
    > > If you don't trust that, then as far as I can understand from OLE.xs and
    > > MSDN
    > >
    > > my $ml_file = $ARGV[0];
    > > my $ML = Win32::OLE->GetObject($ml_file)
    > > or die "can't get a handle on '$ml_file'";
    > >
    > > should allow you to invoke Perl passing it the current filename, and
    > > will use the currently open instance of that file, if any, or open it in
    > > a currently running matlab, if any, or create a new matlab editing that
    > > file. That is, it gets a handle on that file somehow; and I'm *pretty*
    > > sure that if you have it opened and unsaved you get that instance rather
    > > than a new instance from the file. Try it and see (I can't, having
    > > neither matlab nor win32 :) ).

    >
    > I tried using MS Excel to check and see if it functions differently
    > from Matlab and found that if I have an Excel file open
    >
    > my $Count;
    > $Count = Win32::OLE->EnumAllObjects(sub {
    > my $Object = shift;
    > my $Class = Win32::OLE->QueryObjectType($Object);
    > printf "# Object=%s Class=%s\n", $Object, $Class;
    > });
    > print "Found $Count OLE Object(s)\n";
    >
    > Still finds no OLE objects


    Well, no. It's not supposed to. I admit the docs for Win32::OLE are not
    entirely clear, but EnumAllObjects enumerates all OLE objects that have
    been bound to Perl objects in this program, so you can do various sorts
    of cleanup if you need to. It certainly doesn't attempt to enumerate all
    the OLE objects on the system: that would produce quite a list ! The
    docs say it's mostly for debugging.

    > but:
    >
    > my $file = "C:\\MATLAB6p5\\work\\Book1.xls";
    > my $ML = Win32::OLE->GetObject($file)
    > or print "can't get a handle on '$file'";
    > print "$ML\n";
    >
    > Finds the OLE object just fine!! I'm not sure why passing the filename
    > specifically allows it to find the object, but asking for a listing of
    > all OLE objects using EnumAllObjects does not work??
    >
    > As far as Matlab goes, if I have my perl_link.m file open in the matlab
    > program editor (just a text editor in matlab), or if I run perl_link.m
    > in matlab, and this runs my perl script:
    >
    > my $Count;
    > $Count = Win32::OLE->EnumAllObjects(sub {
    > my $Object = shift;
    > my $Class = Win32::OLE->QueryObjectType($Object);
    > printf "# Object=%s Class=%s\n", $Object, $Class;
    > });
    > print "Found $Count OLE Object(s)\n";
    >
    > finds 0 OLE objects (the same as with MS Excel), but unlike excel:


    Well, yes, again :).

    > my $file = "C:\\MATLAB6p5\\work\\perl_link.m";
    > my $ML = Win32::OLE->GetObject($file)
    > or print "can't get a handle on '$file'\n";
    >
    > Returns the following:
    >
    > Win32::OLE(0.1601) error 0x800401e6: "Bad extension for file" at
    > test.pl line 22
    > eval {...} called at test.pl line 22
    > can't get a handle on 'C:\MATLAB6p5\work\perl_link.m'


    Hmm... 0x800401e6 is MK_E_INVALIDEXTENSION, which means (basically) that
    ..m is not properly registered to Matlab. Maybe Matlab doesn't support
    OLE objects for individual files? Alternatively, is there any way you
    can get an OLE moniker for the current document from your matlab macro?
    I've no idea if matlab-macro has any support for OLE stuff, but
    essentially you want to call IMoniker::GetDisplayName on the current
    document object...

    > I'm not sure exactly what this error is, or why ".m" is a "bad
    > extension for file". I'm wondering (Not knowing much about OLE) if
    > there is some way for a program to start without this turned on, and
    > that is why perl is not finding the active instance of matlab??


    I don't really understand what you're asking here...

    > Any other suggestions on ways I might be able to go about doing this
    > before I go ahead and try temp files??


    As I said before,

    > > Firstly, in the common case that there is only one instance of matlab
    > > running then GetActiveObject will do the right thing.


    Ben

    --
    Every twenty-four hours about 34k children die from the effects of poverty.
    Meanwhile, the latest estimate is that 2800 people died on 9/11, so it's like
    that image, that ghastly, grey-billowing, double-barrelled fall, repeated
    twelve times every day. Full of children. [Iain Banks]
    Ben Morrow, Jul 17, 2006
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Patrick.O.Ige

    Ole ole

    Patrick.O.Ige, Jul 16, 2006, in forum: ASP .Net
    Replies:
    0
    Views:
    476
    Patrick.O.Ige
    Jul 16, 2006
  2. Drew Pihera
    Replies:
    0
    Views:
    620
    Drew Pihera
    Feb 4, 2004
  3. siki
    Replies:
    0
    Views:
    936
  4. Luna Moon
    Replies:
    16
    Views:
    1,311
    Giovanni Gherdovich
    Aug 8, 2008
  5. Lance Hoffmeyer
    Replies:
    0
    Views:
    228
    Lance Hoffmeyer
    Nov 17, 2003
Loading...

Share This Page