2009-01-07 97 views
0

我有一个用于3ds Max的自定义插件,它与后端的一些托管代码接口。在某些情况下,我想将一个托管对象转发给MAXScript进行直接交互,即从我的一个函数返回一个包装对象。有没有办法从自定义3ds Max插件返回一个dotNetObject值?

MAXScript能够通过Max中包含的另一个插件(msxdotNet)直接操作被管理对象(我使用的是3ds Max 2008)。它基本上包装了一个对象,并对后期调用使用反射,但它完全自包含,并且没有任何sdk曝光。插件dll本身也不会暴露超过Max所要求的用于添加一些顶级脚本类的最低界面。

的脚本类允许一个通过一个构造

local inst = (dotNetObject "MyPlugin.MyClass" 0 0 "arg3") 

在我来说,我已经有一个我想使用一个对象的实例实例化一个新的对象。

有没有办法从我的插件构建一个dotNetObject包装的实例返回到最大?


Idealy,我想有一个(C++/CLI)类似签名的辅助功能:

Value* WrapObject(System::Object ^obj); 

一些基本保障,我可以做:

  • msxdotNet插件已被加载。
  • msxdotNet插件和我的托管程序集位于同一AppDomain中。

为msxdotNet插件源是包括为SDK示例,但对于管理/清醒的缘故,修改它并重新编译它不是一个选项。

回答

2

我已经解决了这个问题,它利用了由dotNetObject包装的任何CLR对象将自动包装返回值(方法结果和属性值)与另一个包装。这甚至适用于用dotNetClass包装的CLR类型的静态方法和属性。

可以说,我已经得到了我的插件的方法,让我执行任意的MAXScript:

Value* EvalScript(System::String ^script); 

现在我只是需要将对象序列化到一个字符串,然后再返回到活动对象(引用同一个对象,而不仅仅是一个副本!)。

我通过抓住对象的GCHandle,使用GCHandle::ToIntPtr将其转换为blittable并使用GCHandle::FromIntPtr在不同的上下文中实现同一对象来实现此目的。当然,我正在处理这个(并在同一个应用程序域中),否则这是行不通的。

Value* WrapObject(System::Object ^obj) 
{ 
    GCHandle handle = GCHandle::Alloc(obj) 
    try 
    { 
     return EvalScript(System::String::Format(
      L"((dotNetClass \"System.Runtime.InteropServices.GCHandle\").FromIntPtr (dotNetObject \"System.IntPtr\" {0})).get_Target()", 
      GCHandle::ToIntPtr(handle)); 
    } 
    finally 
    { 
     handle.Free(); 
    } 
} 

我已经在真实代码中解释了这一点的评论多于实际代码的10倍。

相关问题