0

バックエンドのマネージド コードと連携する 3ds Max 用のカスタム プラグインがあります。状況によっては、管理対象オブジェクトを MAXScript に転送して直接対話させたい、つまり関数の 1 つからラップされたオブジェクトを返したい場合があります。

MAXScript は、Max に含まれている別のプラグイン (msxdotNet) (私は 3ds Max 2008 を使用しています) を介して、管理対象オブジェクトを比較的うまく直接操作できます。基本的にオブジェクトをラップし、レイト バインド コールにリフレクションを使用しますが、完全に自己完結型であり、sdk の公開はありません。プラグイン dll 自体も、いくつかのトップレベルのスクリプト化されたクラスを追加するために Max が必要とする最小限のインターフェース以上のものを公開しません。

スクリプト化されたクラスにより、コンストラクターを介して新しいオブジェクトをインスタンス化できます

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

私の場合、使用したいオブジェクトのインスタンスが既にあります。

プラグイン内から dotNetObject ラッパーのインスタンスを作成して Max に戻す方法はありますか?


理想的には、次のような (C++/CLI) シグネチャを持つヘルパー関数が必要です。

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

私ができるいくつかの基本的な保証:

  • msxdotNet プラグインは既に読み込まれています。
  • msxdotNet プラグインとマネージ アセンブリは同じ AppDomain にあります。

msxdotNet プラグインのソースはsdkサンプルとして含まれていますが、管理/健全性のために、それを変更して再コンパイルすることはできません。

4

1 に答える 1

2

dotNetObjectでラップされたCLRオブジェクトは、戻り値(メソッドの結果とプロパティ値)を別のラッパーで自動的にラップするという事実を利用して、これを解決しました。これは、dotNetClassでラップされたCLR型の静的メソッドとプロパティにも当てはまります。

プラグインに任意のMAXScriptを実行できるメソッドがすでにあるとしましょう。

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

ここで、オブジェクトを文字列にシリアル化して、アクティブオブジェクト(コピーだけでなく、同じオブジェクトへの参照)に戻す必要があります。

これを行うにGCHandleは、オブジェクトをGCHandle::ToIntPtr取得し、それを使用してブリット可能なものに変換し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倍以上の長さです。

于 2009-04-13T21:49:53.857 に答える