2012-02-28 41 views
61

Nhiều phương pháp trong thư viện .Net được triển khai trong mã gốc. Những người đến từ khuôn khổ chính nó được đánh dấu bằng [MethodImpl(MethodImplOptions.InternalCall)]. Những người đến từ một số DLL không được quản lý được đánh dấu bằng [DllImport] (ví dụ: [DllImport("kernel32.dll")]). Cho đến nay không có gì bất thường.[DllImport ("QCall")] là gì?

Nhưng khi viết answer for another question, tôi phát hiện ra có nhiều phương pháp được đánh dấu bằng [DllImport("QCall")]. Dường như họ đang triển khai nội bộ .Net (ví dụ: GC._Collect()).

Câu hỏi của tôi là: Chính xác [DllImport("QCall")] là gì? Sự khác nhau giữa [DllImport("QCall")][MethodImpl(MethodImplOptions.InternalCall)] là gì?

+1

Đó là cuộc gọi nội bộ đặc biệt; Tôi đang cố tìm chi tiết. – SLaks

+0

Tôi nhớ đã đọc lại một lúc rằng "QCall" là một phần của clr.dll. Tôi, tuy nhiên, không biết nhiều hơn thế. 1 cho một câu hỏi tuyệt vời. – ahawker

+11

Đây là một tính năng .NET 4 cụ thể. Bạn có thể nhận được một chút thông tin chi tiết từ Nguồn tham chiếu V4, xem mã nguồn cho System.Runtime.CompilerServices.Jithelpers.cs. Chuỗi xuất hiện hai lần trong clr.dll, dưới dạng __IsQCall và dưới dạng nội tuyến. Điều này mạnh mẽ giống như một cơ chế mở rộng ngoài MethodImplOptions.InternalCall, chứng minh nó là khó khăn mà không có mã nguồn CLR. –

Trả lời

14

Đây là một chuỗi cũ. Vì CoreCLR hiện đã có nguồn mở trên GitHub; nếu ai đó đang vẫn đang tìm kiếm câu trả lời, đây là official documentation:

Calling from managed to native code

Chúng tôi có hai kỹ thuật để gọi vào CLR từ mã được quản lý. FCall cho phép bạn gọi trực tiếp vào mã CLR, và cung cấp nhiều tính linh hoạt trong việc điều khiển các đối tượng, mặc dù rất dễ gây ra các lỗ GC bằng cách không theo dõi các tham chiếu đối tượng một cách chính xác. QCall cho phép bạn gọi vào CLR thông qua P/Invoke, và khó sử dụng hơn nhiều so với FCall. FCalls được xác định trong mã được quản lý như các phương thức extern với tập bit MethodImplOptions.InternalCall. QCalls là các phương thức extern tĩnh trông giống như P/Invokes thông thường, nhưng đến một thư viện gọi là "QCall".

Có một biến thể nhỏ của FCall gọi là HCall (gọi cho người trợ giúp) để thực hiện JIT helpers, để thực hiện những việc như truy cập các phần tử mảng đa chiều, kiểm tra phạm vi, vv Sự khác biệt duy nhất giữa HCall và FCall là phương pháp HCall sẽ không hiển thị trong một dấu vết ngăn xếp ngoại lệ.

Và sau đó nó tiếp tục trong phân nhóm:

với các ví dụ:

35

Tôi đã hỏi một số người trong nhóm .Net về việc này.

QCalls là các cuộc gọi đến các phương thức gốc trong thời gian chạy CLR. Chúng hoạt động giống như các [DllImport] s khác, nhưng chúng nhanh hơn vì chúng tạo ra các giả định cụ thể (không có giấy tờ) về những gì các phương thức nguyên gốc làm, để chúng có thể bỏ qua các phép kiểm tra khác nhau và GC và ngoại lệ.

InternalCall khác; nó cho các cuộc gọi cho những thứ phản ánh kiểu đặc biệt được tạo ra trong thời gian chạy (điều này không rõ lắm).

0

Bổ sung câu trả lời @SLaks, MethodImplOptions.InternalCall được mô tả ngắn gọn tại đây: ThreadPoolPriority, and MethodImplAttribute.

Về cơ bản InternalCall yêu cầu thời gian chạy kiểm tra bảng tra cứu nội bộ của riêng hàm có tên. Bảng đó tồn tại do tệp nguồn trong mã thời gian chạy khai báo rõ ràng khi thời gian chạy được biên dịch. Nó có một danh sách các con trỏ chức năng để thực hiện tất cả các cuộc gọi nội bộ:

static ECFunc gGuidFuncs[] = { {FCFuncElement("CompleteGuid", NULL, (LPVOID)GuidNative::CompleteGuid)}, {NULL, NULL, NULL} }; 

khai này cho thời gian chạy mà cơ thể phương pháp đối với phương pháp Guid.CompleteGuid quản lý thực sự là nguồn gốc C++ GuidNative :: chức năng CompleteGuid. Bài viết không rõ ràng về cách thức hoạt động của marshaling ở nơi này, nhưng nói chung rõ ràng việc triển khai thời gian chạy, vì cả hai đều khai báo thân hàm [phụ thuộc vào định dạng marshaling] và b) thực hiện bất kỳ marshaling bắt buộc nào .

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