Custom 3DS Max 플러그인에서 dotnetobject 값을 반환하는 방법이 있습니까?
문제
백엔드의 일부 관리 코드와 인터페이스하는 3DS MAX 용 사용자 정의 플러그인이 있습니다. 어떤 상황에서는 직접 상호 작용을 위해 관리되는 객체를 따라 MaxScript로 전달하고 싶습니다. 즉, 내 함수 중 하나에서 랩핑 된 객체를 반환합니다.
MaxScript는 Max (3ds Max 2008을 사용하고 있음)에 포함 된 다른 플러그인 (MSXDOTNET)을 통해 관리 된 객체를 비교적 잘 조작 할 수 있습니다. 기본적으로 물체를 감싸고 늦은 바운드 호출에 반사를 사용하지만 완전히 자체적으로 포함되어 있으며 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 샘플로 포함되지만 관리/Sanity를 위해 수정하고 다시 컴파일하는 것은 옵션이 아닙니다.
해결책
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 배입니다.