2011-09-11 6 views
5

Tôi có một thư viện không được quản lý hiển thị một số giao diện. Người dùng có thể thực hiện các giao diện và gắn chúng vào thư viện với triển khai tùy chỉnh của chúng.Gói được quản lý với giao diện không được quản lý

Tôi muốn cung cấp trình bao bọc được quản lý cho thư viện này. Việc gói một giao diện không được quản lý với giao diện được quản lý rất dễ dàng. Nhưng trong trường hợp của tôi, tôi muốn hỗ trợ việc triển khai thực hiện các giao diện khác nhau có nghĩa là tôi cần thực hiện một giao diện được quản lý và bọc nó bằng cách sử dụng đối tác không được quản lý của nó trước khi gửi nó vào sâu trong phần không được quản lý của thư viện.

tôi đã cố gắng một cái gì đó như:

class UnmanagedWrapper { 
DoSomething() {m_clr.DoSomething();} 
IManaged^ m_clr; 
} 

Nhưng tôi không thể có được quản lý các thành viên trong một lớp không được quản lý, trình biên dịch chính đáng tuyên bố.

Tôi có thể làm gì ở đây không?

+1

Không đủ ngữ cảnh. Sử dụng gcroot <> hoặc Marshal :: GetFunctionPointerForDelegate(). –

Trả lời

0

Dưới đây là một số thông tin liên quan cho công việc xung quanh khi một thư viện không được quản lý và ngôn ngữ được quản lý sử dụng các thư viện đó.

Bối cảnh của thông tin này là một cách để sử dụng GoogleTest trong Visual Studio:

Getting started with Google C++ Testing Framework

Lưu ý quan trọng cho Visual C++ sử dụng Nếu bạn đặt thử nghiệm của bạn thành một thư viện và chính bạn() chức năng nằm trong một thư viện khác hoặc trong tệp tin .exe của bạn, các kiểm tra đó sẽ không chạy. Lý do là một lỗi trong Visual C++. Khi bạn xác định các thử nghiệm của mình, Google Test sẽ tạo một số đối tượng tĩnh là để đăng ký chúng. Các đối tượng này không được tham chiếu từ ở nơi khác nhưng các hàm tạo của chúng vẫn được cho là chạy. Khi Trình liên kết Visual C++ thấy rằng không có gì trong thư viện được tham chiếu từ các địa điểm khác, nó sẽ ném thư viện ra. Bạn phải tham khảo thư viện của mình với các bài kiểm tra từ chương trình chính của bạn để giữ cho trình liên kết khỏi bị xóa . Đây là cách làm. Một nơi nào đó trong mã thư viện của bạn khai báo một hàm:

__declspec (dllexport) int PullInMyLibrary() { return 0; }

Nếu bạn đặt thử nghiệm của bạn trong một thư viện tĩnh (không DLL) sau đó __declspec (dllexport) là

không cần thiết. Bây giờ, trong chương trình chính của bạn, hãy viết một mã mà gọi có chức năng:

int PullInMyLibrary(); 
    static int dummy = PullInMyLibrary(); 

này sẽ giữ kiểm tra của bạn tham chiếu và sẽ làm cho họ đăng ký tự ở khởi động.

Ngoài ra, nếu bạn xác định thử nghiệm của mình trong thư viện tĩnh, hãy thêm /OPT: NOREF vào tùy chọn trình liên kết chương trình chính của bạn. Nếu bạn sử dụng MSVC++ IDE, chuyển đến thuộc tính dự án .exe của bạn/Cấu hình Thuộc tính/Trình liên kết/Tối ưu hóa và đặt Tham chiếu cài đặt thành Keep Dữ liệu không được tham chiếu (/ OPT: NOREF). Điều này sẽ giữ liên kết Visual C++ từ loại bỏ các biểu tượng riêng lẻ do các thử nghiệm của bạn tạo ra từ tệp thực thi cuối cùng.

Tuy nhiên, có thêm một sự cố nữa. Nếu bạn sử dụng Google Test làm thư viện tĩnh (đó là cách nó được xác định trong gtest.vcproj), các thử nghiệm của bạn phải cũng nằm trong thư viện tĩnh. Nếu bạn phải có chúng trong một DLL, bạn phải thay đổi Google Test để xây dựng thành một DLL là tốt. Nếu không, các thử nghiệm của bạn sẽ không chạy chính xác hoặc sẽ không chạy chút nào. Kết luận chung ở đây là: làm cho cuộc sống của bạn dễ dàng hơn - không viết các bài kiểm tra của bạn trong các thư viện !

0

lẽ gcroot<> là những gì bạn muốn:

class UnmanagedWrapper { 
    DoSomething() {m_clr.DoSomething();} 
    gcroot<IManaged^> m_clr; 
} 
0

Bạn cần phải nhập khẩu dll không được quản lý của bạn vào C ứng dụng # Net của bạn. Ví dụ của tôi trả về một con trỏ đến một cấu trúc nhưng bạn có thể cung cấp bất kỳ kiểu trả về nào khác mà ứng dụng của bạn cần. Hãy chắc chắn sử dụng dumpbin.exe/EXPORTS để lấy toàn bộ hàm/tên EntryPoint từ dll. Đây là toàn bộ lớp học của tôi:

using System; 
using System.Runtime.InteropServices; 

namespace aviationLib 
{ 
    public struct MAGtype_GeoMagneticElements 
    { 
     public double Decl; /* 1. Angle between the magnetic field vector and true north, positive east*/ 
     public double Incl; /*2. Angle between the magnetic field vector and the horizontal plane, positive down*/ 
     public double F; /*3. Magnetic Field Strength*/ 
     public double H; /*4. Horizontal Magnetic Field Strength*/ 
     public double X; /*5. Northern component of the magnetic field vector*/ 
     public double Y; /*6. Eastern component of the magnetic field vector*/ 
     public double Z; /*7. Downward component of the magnetic field vector*/ 
     public double GV; /*8. The Grid Variation*/ 
     public double Decldot; /*9. Yearly Rate of change in declination*/ 
     public double Incldot; /*10. Yearly Rate of change in inclination*/ 
     public double Fdot; /*11. Yearly rate of change in Magnetic field strength*/ 
     public double Hdot; /*12. Yearly rate of change in horizontal field strength*/ 
     public double Xdot; /*13. Yearly rate of change in the northern component*/ 
     public double Ydot; /*14. Yearly rate of change in the eastern component*/ 
     public double Zdot; /*15. Yearly rate of change in the downward component*/ 
     public double GVdot; /*16. Yearly rate of change in grid variation*/ 
    }; 

    public class Declination 
    { 
     [DllImport("wmm.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, EntryPoint = "[email protected]@[email protected]@[email protected]")] 
     public static extern IntPtr GeoMagneticElements(float sdate, int igdgc, int units, float alt, float latitude, float longitude); 

     public MAGtype_GeoMagneticElements e; 

     public MAGtype_GeoMagneticElements MagDeclination(float decimalLat, float decimalLon) 
     { 

      try 
      { 
       String d = DateTime.Now.Year.ToString("D4") + '.' + DateTime.Now.Day.ToString("D1"); 
       IntPtr pnt = GeoMagneticElements((float)Convert.ToDouble(d), 1, 3, 3000.0f, decimalLat, decimalLon); 
       e = Marshal.PtrToStructure<MAGtype_GeoMagneticElements>(pnt); 
      } 
      catch (System.EntryPointNotFoundException se) 
      { 
       Console.WriteLine(se.Message); 
      } 

      return e; 
     } 
    } 
} 

Cài đặt từ cần phải giống nhau cho cả quản lý và không được quản lý vì vậy nếu dll là 32 bit thì .NET cũng phải như vậy.