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 $obj->Xyz() 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 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 would greatly appreciate any help - or advise on where to look further.


In reply to Passing COM objects from C# to Perl using PerlNET by mihe

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.