Existe uma maneira para retornar um valor dotNetObject de um 3ds personalizado plug-in Max?

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

  •  05-07-2019
  •  | 
  •  

Pergunta

Eu tenho um plugin personalizado para 3ds Max que as interfaces com algum código gerenciado no back-end. Em algumas circunstâncias, eu gostaria de transmitir ao longo de um objeto gerenciado para MAXScript para interação direta, ou seja, retornar um objeto envolto de uma das minhas funções.

MAXScript é capaz de manipular objetos gerenciados diretamente relativamente bem através de um outro plugin (msxdotNet) incluído com Max (estou usando o 3ds Max 2008). Ele basicamente envolve um objeto e usa a reflexão para chamadas tarde ligados, mas é totalmente auto-suficientes e não tem qualquer exposição SDK. O plugin dll em si também não expõe nada mais do que a interface do mínimo exigido por Max para adicionar um nível superior poucas classes script.

As classes de script permitem instanciar um novo objeto através de um construtor

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

No meu caso eu já tenho uma instância de um objeto que eu gostaria de usar.

Existe uma maneira de construir uma instância de um invólucro dotNetObject de dentro do meu plugin para retornar ao Max?


Idealy, eu gostaria de ter uma função auxiliar com um (++ / CLI C) assinatura semelhante a:

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

Algumas garantias básicas que eu posso fazer:

  • O msxdotNet plug-in já está carregado.
  • O msxdotNet plugin e meus conjuntos gerenciados estão no mesmo AppDomain.

A fonte para a msxdotNet plug-in é incluído como uma amostra SDK, mas para a gestão de amor / de sanidade, modificá-lo e recompilar não é uma opção.

Foi útil?

Solução

Eu já resolveu este, aproveitando o fato de que qualquer objeto CLR envolto por dotNetObject vai embrulhar automaticamente valores de retorno (resultados do método e valores de propriedade) com outro invólucro. Isto mesmo se aplica aos métodos estáticos e propriedades em tipos CLR envolvidas com dotNetClass.

Vamos dizer que eu já tenho um método no meu plugin que me permite executar arbitrária MAXScript:

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

Agora eu só preciso para serializar um objeto em uma string e volta novamente para um objeto ativo (uma referência ao mesmo objeto, e não apenas uma cópia!).

Eu faço isso, agarrando o GCHandle do objeto, usando GCHandle::ToIntPtr para convertê-lo em algo blittable e usando GCHandle::FromIntPtr para materializar o mesmo objeto em um contexto diferente. É claro que eu estou fazendo isso no processo (e no mesmo domínio app), isso não iria funcionar de outra forma.

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

O comentário que eu explicar isso no código real é mais que 10 vezes, desde que o código real.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top