我正在尝试将 COM 对象从 C# 代码传递给 Perl。
目前,我正在使用 PerlNET(PDK 9.4;ActiveState)包装我的 Perl 代码,并且我在 Perl 中定义了一个简单的子例程(+ 所需的 pod 声明)来将对象从 C# 传递到包装的 Perl 模块。
似乎我传递的对象没有被正确识别为 COM 对象。
一个例子:
在 C# (.NET 4.0) 中,ScriptControl 用于从用 VBScript 编写的文件中加载一个简单的类。
var host = new ScriptControl();
host.Language = "VBScript";
var text = File.ReadAllText("TestScript.vbs");
host.AddCode(text);
dynamic obj = host.Run("GetTestClass");
我得到的 ( obj
) 是类型System.__ComObject
。当我将它传递给我的 Perl/PerlNET 程序集并尝试Xyz()
在 Perl 中调用方法时,我得到以下(运行时)异常:
Can't locate public method Xyz() for System.__ComObject
但是,如果我在 Perl 中或多或少地做同样的事情,它就可以工作。(在以下情况下,仅传递我的 .vbs 文件的内容作为参数。)我什至可以使用脚本控件:
sub UseScriptControl {
my ($self, $text) = @_;
my $script = Win32::OLE->new('ScriptControl');
$script->{Language} = 'VBScript';
$script->AddCode($text);
my $obj = $script->Run('GetTestClass');
$obj->Xyz();
}
现在,调用Xyz()
工作obj
正常(使用 Win32::OLE)。
在这两种情况下,我都使用:
use strict;
use Win32;
use Win32::OLE::Variant;
另一种方法:如果我准确指定要使用的重载以及要传递的类型,我可以通过使用类
来调用方法:InvokeMember
System.Type
use PerlNET qw(typeof);
typeof($obj)->InvokeMember("Xyz",
PerlNET::enum("System.Reflection.BindingFlags.InvokeMethod"),
PerlNET::null("System.Reflection.Binder"),
$obj,
"System.Object[]"->new());
使用这种方法意味着重写整个包装的 Perl 模块。并使用这种语法..
现在我想知道,通过将 PerlNET 与 COM 对象结合使用,我是否会同时失去 .NET 4.0 中 dynamic 关键字的优点和 Perl(使用 Win32::OLE)的动态特性。
似乎我首选的解决方案归结为某种模仿dynamic
C#/.NET 4.0 中关键字行为的方式。
或者,更好的是,找到某种方法将传递的 COM 对象转换为可被识别为与Win32::OLE
. 也许提取一些信息__ComObject
以便将其正确识别为 COM 对象。
我必须补充一点,我也发布到了 PDK 讨论网站(但还没有得到任何回复): http: //community.activestate.com/node/18247
我也将它发布到 PerlMonks - 因为我不完全确定这更像是 Perl 还是 C#/.NET 问题:
http ://www.perlmonks.org/?node_id=1146244
我将不胜感激任何帮助 - 或建议在哪里进一步寻找。