4

I’m trying to pass a COM object from C# code to Perl.
At the moment I’m wrapping my Perl code with PerlNET (PDK 9.4; ActiveState) and I have defined a simple subroutine (+ required pod declaration) in Perl to pass objects from C# to the wrapped Perl module.

It seems that the objects I pass are not recognized correctly as COM objects.

An example:
In C# (.NET 4.0), the ScriptControl is used to load a simple class from a file written in VBScript.

var host = new ScriptControl();
host.Language = "VBScript";
var text = File.ReadAllText("TestScript.vbs"); 
host.AddCode(text);

dynamic obj = host.Run("GetTestClass");

What I get (obj) is of type System.__ComObject. When I pass it to my Perl/PerlNET assembly and try to call method Xyz() in Perl I get the following (runtime) exception:

Can't locate public method Xyz() for System.__ComObject

If, however, I do more or less the same thing in Perl, it works. (In the following case, passing only the contents of my .vbs file as parameter.) I can even use the script control :

sub UseScriptControl {
    my ($self, $text) = @_;
    my $script = Win32::OLE->new('ScriptControl');
    $script->{Language} = 'VBScript';
    $script->AddCode($text);
    my $obj = $script->Run('GetTestClass');

    $obj->Xyz();
}

Now, calling Xyz() on obj works fine (using Win32::OLE).

In both cases I use:

use strict;
use Win32;
use Win32::OLE::Variant;

Another approach:
I can invoke methods by using InvokeMember of class System.Type if I specify exactly which overload I want to use and which types I’m passing:

use PerlNET qw(typeof);

typeof($obj)->InvokeMember("Xyz", 
    PerlNET::enum("System.Reflection.BindingFlags.InvokeMethod"), 
    PerlNET::null("System.Reflection.Binder"), 
    $obj, 
    "System.Object[]"->new());

Using this approach would mean rewriting the whole wrapped Perl module. And using this syntax..

Now I am wondering if I am losing both the advantages of the dynamic keyword in .NET 4.0 and the dynamic characteristics of Perl (with Win32::OLE) by using PerlNET with COM objects.

It seems like my preferred solution boils down to some way of mimicking the behaviour of the dynamic keyword in C#/.NET 4.0.

Or, better, finding some way of converting the passed COM object to something that will be recognized as compatible with Win32::OLE. Maybe extract some information of the __ComObject for it to be identified correctly as COM object.

I have to add that I posted to the PDK discussion site too (but didn’t get any response yet): http://community.activestate.com/node/18247
I also posted it to PerlMonks - as I'm not quite sure if this is more a Perl or C#/.NET question: http://www.perlmonks.org/?node_id=1146244

I would greatly appreciate any help - or advise on where to look further.

Miriam
  • 41
  • 3

0 Answers0