2010-05-27 41 views
6

Tôi thực sự bối rối bởi vô số thông tin sai lệch về tương tác gốc/được quản lý.Gọi một cuộc gọi lại từ mã .NET được quản lý (khi tải mã được quản lý bằng COM)

Tôi có một exe C++ thông thường không được xây dựng bằng cách sử dụng công cụ CLR (nó không phải là Managed C++ hay C++/CLI và sẽ không bao giờ). C++ exe này là "phụ trách", không có trình bao bọc được quản lý cho nó.

Tôi muốn truy cập một số mã tôi có trong một C# lắp ráp từ exe C++ của tôi. Tôi có thể truy cập C# assembly từ mã C++ của tôi bằng cách sử dụng COM. Tuy nhiên, khi mã C# của tôi phát hiện một sự kiện, tôi muốn nó gọi lại vào mã C++ của tôi. Con trỏ hàm C++ để gọi lại sẽ được cung cấp khi chạy. Lưu ý rằng con trỏ hàm C++ là một hàm được tìm thấy trong môi trường thực thi của exe. Nó có thể sử dụng các thành viên tĩnh từ đó. Tôi không muốn các mã được quản lý để thử và tải lên một số DLL để gọi một chức năng (không có DLL).

Làm cách nào để chuyển con trỏ hàm C++ này tới mã C# của tôi thông qua COM/.NET và mã C# của tôi gọi thành công?

Cảm ơn!

Trả lời

6

Có thể bạn sẽ muốn sử dụng Marshal.GetDelegateForFunctionPointer:

  1. Tạo một loại đại biểu phù hợp với chữ ký của các chức năng có nguồn gốc, giữ trong tâm trí đúng cách để sắp xếp các loại và sử dụng khi cần thiết MarshalAs
  2. Giao tiếp con trỏ hàm gốc từ mã gốc của bạn tới mã C# của bạn tuy nhiên bạn có thể (trong trường hợp của bạn, có vẻ như bạn có thể sử dụng kết nối COM -> C#)
  3. Sử dụng Marshal.GetDelegateForFunctionPointer để biến con trỏ thành đại biểu C# -callable
  4. Gọi đại biểu với các thông số của bạn

Junfeng Zhang có ví dụ về việc này here.

Lưu ý các hạn chế nêu trên MSDN:

Phương pháp GetDelegateForFunctionPointer có các hạn chế sau:

  • Generics không được hỗ trợ trong interop kịch bản.
  • Bạn không thể chuyển hàm không hợp lệ trỏ đến phương thức này.
  • Bạn chỉ có thể sử dụng phương pháp này cho các con trỏ hàm không được quản lý không được quản lý.
  • Bạn không thể sử dụng phương pháp này với con trỏ hàm thu được thông qua C++ hoặc từ phương thức GetFunctionPointer.
  • Bạn không thể sử dụng phương pháp này để tạo một đại biểu từ một con trỏ hàm tới một đại biểu được quản lý khác.

Phần về C++ có thể đề cập đến con trỏ hàm cho phương thức lớp. Điều này sẽ vẫn làm việc cho các chức năng toàn cầu.

+0

Ở bước 2, con trỏ hàm sẽ đến C# -land dưới dạng IntPtr? – evilfred

+1

Để lấy con trỏ từ C/C++ đến C#, nó sẽ được sắp xếp lại. Có, con trỏ C/C++ được biểu diễn dưới dạng C# 'IntPtr' có kích thước là nền tảng cụ thể. –

+0

Tôi có thể làm điều gì đó câm. Trình biên dịch C++ phàn nàn rằng nó không thể chuyển đổi tham số của tôi từ voic (__ cdecl *) (UINT) thành dài (phương thức lấy IntPtr trong C#). Ngoài ra, ví dụ của Zhang liên quan đến một con trỏ hàm C++ được lấy ra trong C# không được lấy từ C++ ... – evilfred

4

Cách tiếp cận COM chuẩn là đăng ký sự kiện được máy chủ COM nâng lên. Sử dụng có thể sử dụng các từ khóa sự kiện trong C#, CLR interop tự động thực hiện các keo COM đó là cần thiết. Sử dụng giao diện IConnectionPoint trong mã C++ của bạn. Backgrounder is here.

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