2011-11-17 20 views
12

Tôi đang gói một DLL mở rộng MFC (MFCXDLL_2) để làm cho chức năng của nó có sẵn cho các lập trình viên C#.C# .NET Kiểm soát người dùng bên trong ứng dụng gốc. Các vấn đề về chuỗi tài nguyên

Trình bao bọc là "DLL thông thường sử dụng chia sẻ MFC DLL" với "Hỗ trợ thời gian chạy ngôn ngữ chung (/ clr)". (Chế độ hỗn hợp).

Các lớp trong MFCXDLL_2 sẽ có sẵn được trang trí bằng MFCXDLL_3.

Kịch bản mà tôi đang gặp phải là trường hợp MFCXDLL_2 được sử dụng từ điều khiển người dùng C# .NET chạy trong ứng dụng gốc.

Một phần mở rộng MFC DLL -MFCXDLL_1 khác bên trong ứng dụng gốc cũng sử dụng MFCXDLL_2 và điều này gây ra sự cố.

Khi tôi khởi động ứng dụng gốc, nó sẽ ngầm tải MFCXDLL_2.

Khi tôi tải điều khiển người dùng .NET, cùng một MFCXDLL_2 được tải lại một cách rõ ràng theo lời khuyên trong http://msdn.microsoft.com/en-us/library/ksa99t88.aspx, “Sử dụng cơ sở dữ liệu, OLE và ổ cắm DLL mở rộng trong DLL thông thường”.

Cả mã gốc và điều khiển người dùng .NET khởi tạo cùng loại lớp và gọi cùng một phương thức trong MFCXDLL_2.

Phương thức de-serializes dữ liệu (nhận được trên bộ nhớ dùng chung) và trả về dữ liệu đã được tuần tự hóa cho người gọi. Điều này làm việc tuyệt vời từ mã nguồn gốc cho đến khi tôi tải điều khiển người dùng .NET.

Sau khi tải điều khiển người dùng .NET, việc hủy tuần tự ngừng hoạt động từ mã gốc nhưng nó hoạt động tốt khi được gọi từ điều khiển người dùng .NET.

Tôi đã đính kèm WinDbg vào phiên bản gỡ lỗi của ứng dụng gốc và chạy kịch bản của tôi. WinDbg được tìm thấy như sau trong quá trình de-serialization:

“Cảnh báo: Không thể tải từ lưu trữ. Lớp không được xác định. Ngoại lệ giả mạo: badClass. ”

Tôi nghĩ rằng có một số vấn đề về tài nguyên ở đây vì vậy tôi chạy phiên bản phát hành của ứng dụng gốc tải phiên bản phát hành của MFCXDLL_2. Sau đó, tôi tải phiên bản gỡ lỗi của điều khiển người dùng .NET - một lần nữa tải phiên bản gỡ lỗi của MFCXDLL_2- vào ứng dụng gốc.

Sau đó, mọi thứ hoạt động tuyệt vời. Một phiên bản phát hành của MFCXDLL_2 được nạp bằng mã gốc và một phiên bản gỡ lỗi của MFCXDLL_2 được nạp bởi điều khiển người dùng .NET –tất cả đang chạy bên trong ứng dụng gốc.

Vậy điều gì đang xảy ra? Không thể truy cập cùng một MFCXDLL từ ví dụ một phần mở rộng DLL và một DLL thường xuyên cùng một lúc trong cùng một ứng dụng?
Chuỗi tài nguyên có bị phá hủy theo một cách nào đó không? Các giải pháp khả thi là gì?

Dưới đây là một số mã hiển thị MFCXDLL_2 DLL được nạp
cách Khi ứng dụng bản địa bắt đầu MFCXDLL_2 DllMain được gọi là:

static AFX_EXTENSION_MODULE MFCXDLL_2 = { NULL, NULL }; 
static CDynLinkLibrary* gpDynLinkLibrary = NULL; 

extern "C" int APIENTRY 
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID) 
{ 
    if (dwReason == DLL_PROCESS_ATTACH) 
    { 
     // Extension DLL one-time initialization 
     AfxInitExtensionModule(MFCXDLL_2, hInstance); 

     // Insert this DLL into the resource chain 
     gpDynLinkLibrary = new CDynLinkLibrary(MFCXDLL_2); 
    } 
    else if (dwReason == DLL_PROCESS_DETACH) 
    { 
     if (gpDynLinkLibrary) 
     { 
       delete gpDynLinkLibrary; 
       gpDynLinkLibrary = NULL; 
     } 
     // Terminate the library before destructors are called 
     AfxTermExtensionModule(MFCXDLL_2); 
    } 
    return 1; // ok 
} 

Khi.điều khiển người dùng NET được nạp, các MFCXDLL_2 DLL được nạp một lần nữa:

//============================================================== 
// Exported DLL initialization to run in context of Regular DLL. 
// Must be called in InitInstance 
// BOOL CYourRegularDLLApp::InitInstance() 
//============================================================== 
extern "C" _declspec(dllexport) CDynLinkLibrary* WINAPI InitMFCXDLL_2FromRegularDLL() 
{ 
    if (gpDynLinkLibrary) 
    { 
     delete gpDynLinkLibrary; 
     gpDynLinkLibrary = NULL; 
    } 
    // Create a new CDynLinkLibrary for this Regular DLL 
    return new CDynLinkLibrary(MFCXDLL_2); 
} 

Mã deserialize bên MFCXDLL_2

CMyClass* pMyclass = NULL; //CObject derived serializeable class 
    BYTE *pBuf  = pGlobalCom->GetBuffer(); //Buffer with serialized CMyClass 
    int nBufSize = pGlobalCom->GetSize(); //Size of buffer 

    CMemFile mf; 
    mf.Attach(pBuf,nBufSize); 

    CArchive ar(&mf, CArchive::load); //“Warning: Cannot load CMyClass from archive. Class not defined.CArchive exception: badClass.” 

    ar >> pMyclass; //CArchive exception thrown 
    ar.Close(); 
    mf.Detach(); 

Những hình ảnh cho thấy mối quan hệ giữa dlls.

enter image description here

Trả lời

1

Tôi nghĩ rằng bạn có thể có một số nhầm lẫn ở đây như những gì wrapper của bạn đang làm.

Bạn có thể gọi không được quản lý C++ DLL từ trong mã .NET bằng cách sử dụng các câu lệnh DLLImport.

Tôi khuyên bạn nên tạo một dự án thư viện lớp C# sẽ là trình bao bọc DLL cho DLL không được quản lý của bạn, MFCXDLL.

Bạn có thể không thêm DLL làm tài nguyên tham chiếu, nhưng bạn nên tạo thư mục dự án mà bạn lưu trữ và thêm nó dưới dạng tệp dự án, đặt thành Sao chép địa phương đúng cho khi thư viện lớp NET được xây dựng. Bạn cũng sẽ muốn đặt bất kỳ tệp DLL nào mà MFCXDLL tham chiếu trong cùng một thư mục cũng được đặt thành Sao chép cục bộ.

Sau đó, bạn tham khảo NET DLL của mình từ tất cả mã dựa trên NET.

Here là ví dụ về quy trình trình bao bọc.

chỉnh sửa

Tôi đã có một tấm séc và vâng tôi đã sử dụng một không quản C++ DLL mà sử dụng MFC là một thư viện chia sẻ. Đây là một phiên bản cắt giảm của mã mà tôi đã sử dụng. (Một số tên lớp đã được thay đổi do thỏa thuận bảo mật.)

using System.Collections.Generic; 
    using System.Runtime.InteropServices; 

    public class WrapperClass 
    { 
     [DllImport("some.dll", EntryPoint = "WriteDataCard", SetLastError = true)] 
     [return: MarshalAs(UnmanagedType.VariantBool)] 
     public static extern Boolean WriteDataCard(Byte nComPort, bool bInitialize, bool bCardFeeder, [In] Byte[] bytesData, Byte dataSize, bool bTestKey); 

     [DllImport("some.dll", EntryPoint = "ReadDataCard", SetLastError=true)] 
     [return: MarshalAs(UnmanagedType.VariantBool)] 
     public static extern Boolean ReadDataCard(Byte nComPort, Boolean bInitialize, Boolean bCardFeeder, [Out] Byte[] bytesData, Byte dataSize); 

    } 
+0

Tôi có thể xem cách C# Wrapper giải quyết vấn đề. Làm cách nào để giải quyết sự cố? Tôi đang theo mẫu được đưa ra trong bài viết http://www.codeguru.com/cpp/cpp/cpp_managed/interop/article.php/c6867. Cầu nối thực tế giữa thế giới được quản lý và không được quản lý là DLL chế độ hỗn hợp. Trình bao bọc chỉ trang trí các lớp mà tôi muốn hiển thị cho điều khiển người dùng .NET. – kjella

+0

Bạn nói đúng. Hình ảnh đã sai. Đó là tất nhiên là "thường xuyên dll sử dụng chia sẻ MFC DLL" đó là wrapper. Tôi đã thay đổi hình ảnh ngay bây giờ. Các MFCXDLL_3 trang trí một vài trong số các lớp học trong MFCXDLL_2 và làm cho chức năng cần thiết có sẵn cho người dùng kiểm soát. – kjella

+0

Mẫu CodeGuru mà bạn đang xem là từ năm 2004. Tôi khá chắc chắn rằng nó không còn áp dụng (ít nhất là cho NET 3.5 trở đi). Tôi có thể kiểm tra lại bằng mã mà tôi có trên một máy khác và sẽ đăng lại sau. – ChrisBD

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