2009-01-07 64 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倍。

相關問題