¿Hay alguna manera de devolver un valor dotNetObject desde un complemento personalizado de 3ds Max?

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

  •  05-07-2019
  •  | 
  •  

Pregunta

Tengo un complemento personalizado para 3ds Max que interactúa con algún código administrado en el back-end. En algunas circunstancias, me gustaría reenviar un objeto administrado a MAXScript para la interacción directa, es decir, devolver un objeto envuelto desde una de mis funciones.

MAXScript es capaz de manipular objetos administrados directamente relativamente bien a través de otro complemento (msxdotNet) incluido con Max (estoy usando 3ds Max 2008). Básicamente envuelve un objeto y usa la reflexión para las llamadas vinculadas tardías, pero es totalmente independiente y no tiene ninguna exposición de SDK. El complemento dll en sí mismo no expone nada más que la interfaz mínima requerida por Max para agregar algunas clases de scripts de nivel superior.

Las clases con secuencias de comandos permiten crear una instancia de un nuevo objeto a través de un constructor

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

En mi caso, ya tengo una instancia de un objeto que me gustaría usar.

¿Hay alguna manera de construir una instancia de un contenedor dotNetObject desde mi plugin para volver a Max?


Idealmente, me gustaría tener una función de ayuda con una firma (C ++ / CLI) similar a:

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

Algunas garantías básicas que puedo hacer:

  • El complemento msxdotNet ya está cargado.
  • El complemento msxdotNet y mis ensamblados administrados están en el mismo dominio de aplicación.

La fuente del complemento msxdotNet se incluye como una muestra de SDK, pero por el bien de la administración / sanidad, modificarlo y recompilarlo no es una opción.

¿Fue útil?

Solución

Resolví esto al aprovechar el hecho de que cualquier objeto CLR envuelto por dotNetObject envolverá automáticamente los valores de retorno (resultados del método y valores de propiedad) con otra envoltura. Esto incluso se aplica a los métodos y propiedades estáticos en los tipos CLR envueltos con dotNetClass.

Digamos que ya tengo un método en mi complemento que me permite ejecutar MAXScript arbitrario:

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

Ahora solo necesito serializar un objeto en una cadena y volver a un objeto activo (¡una referencia al mismo objeto, no solo una copia!).

Hago esto al agarrar el GCHandle del objeto, usando GCHandle :: ToIntPtr para convertirlo en algo que se pueda mezclar y usando GCHandle :: FromIntPtr para materializar el mismo objeto en un contexto diferente. Por supuesto que estoy haciendo esto en proceso (y en el mismo dominio de la aplicación), esto no funcionaría de otra manera.

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

El comentario que tengo explicando esto en el código real es más de 10 veces mayor que el código real.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top