Interfacing with Matlab using Win32::OLE

S

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.

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";
 
B

Ben Morrow

Quoth "scottmf said:
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.
#!/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
 
S

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

Ben Morrow

Quoth "scottmf said:
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?
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
 
B

Ben Morrow

Quoth "A. Sinan Unur said:
Quoth "scottmf said:
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
 
S

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

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
 
B

Ben Morrow

Quoth "scottmf said:
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,

Ben
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,152
Members
46,698
Latest member
LydiaHalle

Latest Threads

Top