2010-03-27 51 views
5

Tôi khá mới với COM nên câu hỏi có vẻ ngây thơ.Câu hỏi mới về COM

Q1. Giới thiệu về Windows DLL

Dựa trên sự hiểu biết của tôi, Windows DLL có thể xuất chức năng, loại (lớp) và biến toàn cầu. Sự hiểu biết này có ổn không?

Q2. Giới thiệu về COM

Sự hiểu biết ngây thơ của tôi là: COM DLL dường như chỉ là một cách hợp lý mới để tổ chức các chức năng và các loại được xuất bởi một DLL Windows chuẩn. Một COM DLL xuất khẩu cả hai chức năng như EFS()DllGetClassObject(), và cũng là Lớp mà thực hiện giao diện IUnknown. Sự hiểu biết này có ổn không?

Q3. * .def & * .idl

* .def được sử dụng để xác định các chức năng xuất khẩu của Windows DLL theo cách truyền thống, chẳng hạn như DllGetClassObject(). * .idl được sử dụng để xác định giao diện được thực hiện bởi một COM coclass.

Xin cảm ơn trước.

Trả lời

14

Hãy nghĩ COM là một cách tương thích nhị phân để chia sẻ giao diện qua ranh giới DLL. Các lớp C++ không thể dễ dàng được xuất từ ​​các tệp DLL vì tên mangling không chuẩn được thực hiện giữa các phiên bản trình biên dịch khác nhau. COM cho phép mã trong một DLL hoặc thực thi, để tạo ra một thực hiện của một giao diện từ một DLL hoặc EXE miễn là thực hiện sau một giao diện được xác định và gọi quy ước. Đây là những gì cho phép một lớp COM được viết bằng C# và được gọi từ C++, Python và nhiều ngôn ngữ nhận thức COM khác.

Giao diện COM chỉ là các lớp C++ chuẩn chứa tất cả các hàm ảo thuần túy và bắt nguồn từ IUnknown. IUnknown là một giao diện được xác định trước rằng tất cả các giao diện COM tuân thủ phải lấy được từ đó cung cấp các cơ sở phổ biến như tính tham chiếu và khả năng truy vấn xem một đối tượng có thực hiện một giao diện cụ thể hay không.

DLL có nhu cầu quảng cáo thực tế họ có thể tạo triển khai các giao diện COM làm như vậy bằng cách xuất 4 chức năng:

  • DllGetClassObject => Return một nhà máy lớp của một giao diện yêu cầu
  • DllCanUnloadNow => Cho dù tất cả trường hợp trao đã được thả
  • DllRegisterServer => đăng ký các loại DLL này cung cấp trong registry
  • DllUnregisterServer => Unregister DLL này và các loại từ registry

Vì vậy, để giải đáp thắc mắc của bạn:

Q1. Về Windows DLL Dựa trên sự hiểu biết của tôi, một DLL Windows có thể xuất chức năng, loại (lớp) và biến toàn cầu. Sự hiểu biết này có ổn không?

Dll có thể xuất chức năng và lớp học (không chắc chắn về biến toàn cầu, nhưng bạn không muốn xuất chúng DLL ngay cả khi bạn có thể! :-)) Tuy nhiên, các lớp được xuất sẽ bị xáo trộn và do đó chỉ có thể sử dụng bởi các tệp DLL hoặc EXE khác có cùng tên mangling (không phải là cách tốt để làm kinh doanh). Chức năng với quy ước gọi điện thoại kiểu C không phải là tên bị xé và do đó có thể được xuất và gọi từ nơi khác mà không gặp sự cố.

Q2. Một COM DLL xuất khẩu cả hai chức năng như DllRegisterServer() và DllGetClassObject(), và cũng là các lớp học mà thực hiện các giao diện IUnknown. Sự hiểu biết này là tất cả phải không?

Nửa chừng, có 4 chức năng để xuất thành tệp COM tuân thủ đầy đủ COM (được hiển thị ở trên). Bạn có thể tìm kiếm MSDN cho bất kỳ tên nào trong số những tên đó để xem các chữ ký đầy đủ. Việc triển khai DllGetClassObject của bạn sẽ là phần chính mà bên ngoài sẽ sử dụng. Họ có thể sử dụng để có được một IClassFactory đến một giao diện DLL của bạn cung cấp, và sau đó sử dụng nó để tạo một thể hiện.

COM là một con thú lớn và phức tạp, nhưng cơ sở của nó khá đơn giản. Bạn cũng có thể xem liên kết này COM Intro để biết thêm thông tin. Chúc may mắn!

+0

+1 COM không phải là điên rồ. Nó cho phép bạn kết nối các ngôn ngữ cấp cao trong một khoảng cách mức thấp. – pestilence669

4

Bạn có tất cả chính xác cho đến thời điểm này. Các bit duy nhất tôi sẽ làm rõ là "các lớp học mà thực hiện các giao diện IUnknown." Một lớp được đại diện bởi một đối tượng thực hiện giao diện IClassFactory. Bạn có thể nhận được một nhà máy lớp học như vậy bằng cách gọi DllGetClassObject trong một DLL, và sau đó bạn có thể yêu cầu nhà máy của lớp tạo ra một đối tượng của lớp. Điều này tương tự như nhiều hệ thống hướng đối tượng khác: có nhiều đối tượng đại diện cho các lớp và có thể được sử dụng để tạo ra các cá thể.

sự kiện hữu ích khác về COM:

  • Có một thư viện nhỏ nhưng phức tạp của các chức năng helper, chủ yếu là đặt tên với tiền tố Co. Đó là những thực sự tải các DLL, xác định vị trí các chức năng xuất khẩu và gọi chúng. Mã máy khách thường không gọi trực tiếp DLL xuất khẩu (mặc dù nó là một vấn đề khá đơn giản để viết hệ thống lưu trữ của riêng bạn cho các đối tượng COM đơn giản trong quá trình).
  • Có một giao diện quan trọng IDispatch bổ sung thêm một lớp trừu tượng khác để có thể xác định động các phương thức để gọi đối tượng, sử dụng chuỗi để tìm phương thức và truyền một mảng giá trị đối số. Điều này cho phép các ngôn ngữ kịch bản gọi các đối tượng COM một cách an toàn (tức là theo cách chịu đựng sai sót của lập trình viên thay vì bị lỗi).
  • Có một hệ thống "marshalling" phức tạp hơn để cho phép các đối tượng được gọi từ các chủ đề khác, các quy trình khác hoặc thậm chí các máy tính khác; trong điều khiển từ xa (và nhận thức bảo mật) của nó đối với biểu mẫu, nó được gọi là DCOM. Nó đã không thành công trên bất cứ điều gì giống như quy mô mà tập quán COM khác đã làm.
  • Sự hỗ trợ chéo là cơ sở của OLE2, một mánh lới quảng cáo mà mọi ứng dụng đổ xô hỗ trợ vào đầu những năm 1990, hầu hết trong số họ triển khai các giao diện (rất phức tạp) một cách sai lầm và đổ vỡ khắp nơi.
  • Xa thành công hơn là điều khiển OLE, kỹ thuật đơn giản hơn rất nhiều (không sử dụng marshalling) và cung cấp một cách để mở rộng Visual Basic.
  • Có ít nhất một hệ thống cảm hứng COM được phân phối rộng rãi không tương thích với COM nhưng chia sẻ chính xác cùng một khái niệm (ít nhất là các công cụ đơn giản), được gọi là XPCOM và là cơ sở của trình duyệt Web Mozilla Firefox.
  • Nếu bạn sử dụng COM phổ biến, bạn sẽ có một cách tuyệt vời để tích hợp với khuôn khổ .NET, vì nó bao gồm khả năng tương tác tuyệt vời với COM. Nhưng bạn phải tuân theo quy tắc của COM chính xác: AddRef/Release phải hoạt động chính xác như được xác định, vì vậy đối tượng không bao giờ bị hủy trong khi số tham chiếu lớn hơn 0, phải có thể sử dụng QueryInterface để tìm IUnknown từ bất kỳ giao diện nào và từ đó để quay lại giao diện ban đầu, IUnknown thu được từ bất kỳ giao diện nào phải luôn có cùng địa chỉ bộ nhớ cho toàn bộ thời gian của đối tượng (vì vậy nó có thể được sử dụng để so sánh danh tính). Vì vậy, ví dụ: không tạo đối tượng COM trên ngăn xếp, và không trả về các đối tượng riêng biệt từ QueryInterface (có nghĩa là, đối tượng có riêng của họ QueryInterface trả về các giao diện khác nhau).
  • Gotcha chính với COM là nó có ít nhất hai cách tiêu chuẩn đại diện cho chuỗi. Không sử dụng tính tham chiếu. Tại sao họ không bao giờ xác định một giao diện IString là ngoài tôi, nhưng họ đã không.
  • Bạn sẽ phát điên nếu bạn cố gắng viết mã COM mà không có con trỏ thông minh để giữ tham chiếu hoặc không có lớp cơ sở để giúp bạn triển khai giao diện, ví dụ: class MyClass : COM::Object<IThis, IThat> {...)
5

Để thêm vào câu trả lời hay của cpalmer, không có lý do cụ thể tại sao bạn cần sử dụng đăng ký và bốn chức năng được đề xuất để xuất COM từ DLL của bạn.

Bạn có thể sử dụng một COM đăng ký miễn phí, hoặc cách tiếp cận COM-lite, nơi bạn chỉ đơn giản là phương pháp nhà máy xuất khẩu, chẳng hạn như

__declspec (dllexport) void MyDllCreateFoo (IFoo ** ppFoo);

Người dùng DLL sẽ gọi cho nhà máy của bạn để tạo lớp CMyFoo của bạn triển khai IFoo. Những gì DllRegisterServer et. al. làm là cho phép CMyFoo và các lớp khác được tra cứu trong registry, trong số những thứ khác.

Q3: Bạn thực sự đúng, nếu không theo tinh thần. Các tệp .def và các tệp .idl là các con thú khá khác nhau. Các tệp .def chỉ được sử dụng bởi trình liên kết và thậm chí không cần thiết - bạn có thể xuất tất cả các chức năng bạn muốn sử dụng __declspec (dllexport) void foo() { }

bên trong mã C++ của bạn.

.idl tệp được sử dụng để tạo tiêu đề C++ (tệp .h) được bao gồm cả bởi DLL cũng như khách hàng của nó. Nó tạo ra các giao diện cộng với một số mã keo làm những việc như tham số mashalling.

Một lần nữa, bạn không cần phải sử dụng công nghệ IDL để sử dụng COM, nhưng nó có thể làm cho mọi thứ thuận tiện hơn.

Lý do tôi chia nhỏ nó như thế này là để minh họa rằng COM không phải là một khối nguyên khối lớn, mà là một thứ rất nhỏ với nhiều thứ được xây dựng xung quanh nó mà bạn có thể chọn sử dụng hoặc không , nếm thử.

+0

Cảm ơn rất nhiều, Drew. Có, đó là chính xác những gì tôi đang suy nghĩ về để xuất khẩu các phương pháp nhà máy trực tiếp. Bởi vì tôi chỉ cảm thấy rằng nó chỉ là tẻ nhạt để xuất một phương thức DllGetClassObject(). Tôi đã không nhận ra nó đã có và được gọi là reg-miễn phí COM cho đến khi nhìn thấy câu trả lời của bạn, cảm ơn một lần nữa. – smwikipedia

+0

xin lỗi vì tôi chỉ có thể đánh dấu 1 câu trả lời là câu trả lời. – smwikipedia