문제

설명된 것과 유사하지만 미묘하게 다른 문제가 있습니다. 여기 (어셈블리 및 해당 종속성 로드)

저는 우리가 고객에게 판매하는 3D 렌더링용 C++ DLL을 가지고 있습니다..NET 사용자의 경우 CLR 래퍼가 있습니다.C++ DLL은 32비트 버전과 64비트 버전 모두에서 빌드할 수 있지만 이는 CLR이 특정 DLL에 바인딩되므로 두 개의 CLR 래퍼가 필요하다는 의미라고 생각합니다.

이제 고객이 32비트 또는 64비트일 수 있는 .NET 앱을 가지고 있고 이 앱이 순수 .NET 앱이므로 CLR을 통해 단일 어셈블리 집합에서 작업할 수 있다고 가정해 보겠습니다.문제는 앱 코드가 런타임에 32비트와 64비트 CLR/DLL 조합 중에서 어떻게 동적으로 선택할 수 있느냐는 것입니다.

더욱 구체적으로, 앞서 언급한 질문에 대해 제안된 답변이 여기에도 적용 가능합니까(예:ResolveEvent 핸들러를 생성하시겠습니까?

도움이 되었습니까?

해결책

마침내 작동하는 것으로 보이는 이에 대한 답을 얻었습니다.

32비트 및 64비트 버전(관리형 및 비관리형 모두)을 별도의 폴더로 컴파일합니다.그런 다음 .NET 앱이 런타임에 어셈블리를 로드할 디렉터리를 선택하도록 합니다.

ResolveEvent를 사용할 때의 문제점은 어셈블리를 찾을 수 없는 경우에만 호출되므로 실수로 32비트 버전이 되기 쉽습니다.대신 올바른 폴더를 가리키도록 ApplicationBase 속성을 변경할 수 있는 두 번째 AppDomain 개체를 사용하세요.따라서 다음과 같은 코드가 생성됩니다.

static void Main(String[] argv)
  {
     // Create a new AppDomain, but with the base directory set to either the 32-bit or 64-bit
     // sub-directories.

     AppDomainSetup objADS = new AppDomainSetup();

     System.String assemblyDir = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
     switch (System.IntPtr.Size)
     {
        case (4): assemblyDir += "\\win32\\";
           break;
        case (8): assemblyDir += "\\x64\\";
           break;
     }

     objADS.ApplicationBase = assemblyDir;

     // We set the PrivateBinPath to the application directory, so that we can still
     // load the platform neutral assemblies from the app directory.
     objADS.PrivateBinPath = System.IO.Path.GetDirectoryName(Application.ExecutablePath);

     AppDomain objAD = AppDomain.CreateDomain("", null, objADS);
     if (argv.Length > 0)
        objAD.ExecuteAssembly(argv[0]);
     else
        objAD.ExecuteAssembly("MyApplication.exe");

     AppDomain.Unload(objAD);

  }

결국 일반 앱과 로드할 비트를 선택하는 두 번째 전환 앱이라는 2개의 exe가 생성됩니다.참고 - 이 세부 사항에 대해서는 나 자신의 공로를 인정할 수 없습니다.내 동료 중 한 명이 내 초기 조언을 듣고 그 점을 의심했습니다.만약 그가 StackOverflow에 가입하면 나는 그에게 답변을 할당할 것입니다

다른 팁

약 1년 전에 이 작업을 수행할 수 있었지만 더 이상 모든 세부 사항을 기억하지 못합니다.기본적으로 IntPtr.Size를 사용하여 로드할 DLL을 결정한 다음 p/Invoke를 통해 실제 LoadLibrary를 수행할 수 있습니다.그 시점에서 메모리에 모듈이 있고 그 내부에서 함수를 p/Invoke할 수 있어야 합니다. 동일한 모듈 이름이 다시 로드되어서는 안 됩니다.

하지만 내 응용 프로그램에서는 실제로 C++ DLL 자체를 COM 서버로 등록한 다음 생성된 .NET 래퍼를 통해 해당 기능에 액세스했다고 생각합니다. 따라서 p/Invoking을 직접 테스트한 적이 있는지는 모르겠습니다.

나는 얼마 전에 비슷한 시나리오를 겪었습니다.제가 사용하고 있던 툴킷은 64비트 환경에서 제대로 작동하지 않았고 어셈블리를 32비트로 바인딩하도록 동적으로 강제하는 방법을 찾을 수 없었습니다.

어셈블리가 32비트 모드에서 작동하도록 강제할 수 있지만 이를 위해서는 CLR 헤더를 패치해야 하며(프레임워크에 해당 작업을 수행하는 도구가 있음) 어셈블리의 이름이 강력하면 이 작업이 작동하지 않습니다.

유감스럽게도 32비트 및 64비트 플랫폼용 바이너리 세트 두 개를 빌드하고 게시해야 합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top