Gibt es eine Möglichkeit, einen dotNetObject Wert von einem benutzerdefinierten 3ds Max Plugin zurück?

StackOverflow https://stackoverflow.com/questions/421566

  •  05-07-2019
  •  | 
  •  

Frage

Ich habe eine benutzerdefinierte Plug-In für 3ds Max, die mit Schnittstellen einige Code auf der Rückseite Ende geführt werden. In einigen Fällen, würde ich an einem verwalteten Objekt zu MAXScript für direkte Interaktion weiterleiten möchte, das heißt Rück ein verpacktes Objekt von einem meiner Funktionen.

MAXScript der Lage ist, verwalteten Objekte durch ein anderes Plugin relativ gut direkt zu manipulieren (msxdotNet) mit Max enthalten (Ich bin mit 3ds Max 2008). Es wickelt im Grunde ein Objekt und verwendet Reflektion für spät gebunden Anrufe, aber es ist völlig eigenständig und hat keine sdk Exposition. Das Plugin dll sich auch aussetzen nichts mehr als die minimale Schnittstelle von Max erforderlich für das Hinzufügen von ein paar Top-Level-Skript-Klassen.

Die Skript-Klassen ermöglichen ein neues Objekt über einen Konstruktor zu instanziiert

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

In meinem Fall habe ich bereits eine Instanz eines Objekts, das ich verwenden möchte.

Gibt es eine Möglichkeit, eine Instanz eines dotNetObject Wrapper aus meinem Plugin Max zurückkehren zu bauen?


Idealy, würde Ich mag eine Hilfsfunktion haben, mit einer (C ++ / CLI) Signatur ähnlich wie:

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

Einige grundlegende Garantien, dass ich machen kann:

  • Das msxdotNet Plugin ist bereits geladen.
  • Die msxdotNet Plugin und meine verwalteten Baugruppen sind in derselben AppDomain.

Die Quelle für das msxdotNet Plugin ist als sdk Probe enthalten, aber für das Management / Vernunft willen, es zu ändern und neu zu kompilieren es ist keine Option.

War es hilfreich?

Lösung

Ich habe dieses Problem gelöst, indem die Tatsache nutzen, dass jedes CLR-Objekt von dotNetObject gewickelt wird automatisch Rückgabewert (Methode Ergebnisse und Eigenschaftswerte) mit einem anderen Wrapper wickelt. Dies gilt auch für statische Methoden und Eigenschaften auf CLR-Typ eingewickelt mit dotNetClass.

Nehmen wir an ich habe bereits ein Verfahren in meinem Plugin, das mir willkürlich MAXScript können ausführen:

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

Jetzt brauche ich nur ein Objekt in einen String serialisiert und wieder zurück zu einem aktiven Objekt (ein Verweis auf das gleiche Objekt, nicht nur eine Kopie!).

Ich tue dies, indem Sie die GCHandle des Objekts greift, mit GCHandle::ToIntPtr es um etwas blitfähig zu konvertieren und mit GCHandle::FromIntPtr dem gleichen Objekt in einem anderen Kontext zu verwirklichen. Natürlich habe ich diese (und in der gleichen Anwendungsdomäne) in Prozess tue, ist dies nicht anders funktionieren würde.

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();
    }
}

Der Kommentar, den ich dies in dem realen Code zu erklären habe, ist mehr als 10x so lang wie der eigentliche Code.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top