2008-08-22 25 views
16

Tôi đã có một vấn đề tương tự, nhưng tinh tế khác với, mô tả here (Loading hội đồng và phụ thuộc của họ).Làm thế nào để kết thúc muộn 32bit/64 bit libs tại thời gian chạy

Tôi có một DLL C++ để dựng hình 3D là những gì chúng tôi bán cho khách hàng. Đối với người dùng .NET, chúng ta sẽ có một trình bao bọc CLR xung quanh nó. DLL C++ có thể được xây dựng trong cả hai phiên bản 32 và 64bit, nhưng tôi nghĩ điều này có nghĩa là chúng ta cần có hai trình bao bọc CLR vì CLR liên kết với một DLL cụ thể?

Giả sử khách hàng của chúng tôi có một ứng dụng .NET có thể là 32 hoặc 64 bit, và nó là một ứng dụng .NET thuần túy, nó rời khỏi CLR để làm việc nó từ một tập hợp duy nhất. Câu hỏi đặt ra là làm thế nào mã ứng dụng có thể tự động lựa chọn giữa các kết hợp CLR/DLL 32 và 64bit của chúng tôi vào thời gian chạy?

Thậm chí cụ thể hơn, là câu trả lời được đề xuất cho câu hỏi nói trên cũng có thể áp dụng ở đây (ví dụ: tạo trình xử lý ResolveEvent)?

Trả lời

8

Cuối cùng tôi có câu trả lời cho điều này dường như hoạt động.

Biên dịch cả hai 32 & Phiên bản 64 bit - cả hai được quản lý & không được quản lý - vào các thư mục riêng biệt. Sau đó, có ứng dụng .NET chọn lúc chạy thư mục để tải các assembly từ đó.

Vấn đề với việc sử dụng ResolveEvent là nó chỉ được gọi nếu không tìm thấy hội đồng, do đó, nó là tất cả để dễ dàng vô tình kết thúc với phiên bản 32 bit. Thay vào đó, hãy sử dụng đối tượng AppDomain thứ hai, nơi chúng ta có thể thay đổi thuộc tính ApplicationBase để trỏ vào thư mục bên phải. Vì vậy, bạn kết thúc bằng mã như:

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

    } 

Bạn kết thúc bằng 2 ứng dụng thông thường và ứng dụng chuyển đổi thứ hai chọn các bit cần tải. Lưu ý - Tôi không thể tự ghi nhận chi tiết về điều này. Một trong những đồng nghiệp của tôi đã nói lên điều đó với con trỏ ban đầu của tôi. Nếu và khi anh ấy đăng ký vào StackOverflow tôi sẽ chỉ định câu trả lời cho anh ấy

1

Tôi đã gặp phải tình huống tương tự trong khi quay lại. Một bộ công cụ tôi đang sử dụng không hoạt động tốt trong môi trường 64-bit và tôi không thể tìm ra cách để tự động buộc các hội đồng liên kết với nhau như là 32 bit.

Có thể buộc các hội đồng của bạn hoạt động ở chế độ 32 bit, nhưng điều này đòi hỏi phải vá tiêu đề CLR, (có một công cụ thực hiện điều đó trong Khung) và nếu hội đồng của bạn được đặt tên mạnh, điều này không tập thể dục.

Tôi e rằng bạn sẽ cần xây dựng và xuất bản hai bộ mã nhị phân cho nền tảng 32 và 64 bit.

3

Tôi đã có thể thực hiện việc này khoảng một năm trước, nhưng tôi không còn nhớ tất cả chi tiết nữa. Về cơ bản, bạn có thể sử dụng IntPtr.Size để xác định DLL cần tải, sau đó thực hiện LoadLibrary thực tế thông qua p/Invoke. Tại thời điểm đó, bạn đã có các mô-đun trong bộ nhớ và bạn nên có khả năng chỉ p/Gọi hàm từ bên trong của nó - tên mô-đun tương tự không nên tải lại một lần nữa. Tôi nghĩ, mặc dù, trong ứng dụng của tôi, tôi đã thực sự có C++ DLL đăng ký chính nó như là một máy chủ COM và sau đó truy cập chức năng của nó thông qua một wrapper .NET tạo ra - vì vậy tôi không biết nếu tôi đã bao giờ thử nghiệm p/Gọi trực tiếp.

Các vấn đề liên quan