2010-08-26 37 views
5

Câu hỏi của tôi liên quan chặt chẽ đến cách một DLL xuất các lớp C++ và các phương thức chung (các tính năng ngôn ngữ wrt C++ không có C# song song).Làm cách nào để sử dụng thư viện C++ từ C# và .NET?

Tôi tin rằng bạn có thể gọi các hàm bên trong một khối extern "C" từ C# bằng cách chỉ tham chiếu tệp DLL và sử dụng DLLImport. Nhưng bạn có thể khởi tạo một loại C++ templated? Điều gì xảy ra nếu loại C++ thực hiện somethin' crazy không được hỗ trợ trong C#? Có một RFC hoặc một phần liên quan của C# specification không?

Thanks ...

EDIT: bây giờ tôi stumbled trên P/Invoke mà nên có giá trị, nhưng tôi vẫn đang tìm kiếm một đặc điểm kỹ thuật hoặc tiêu chuẩn về vấn đề này.

Trả lời

7

Cách sane để làm điều đó là sử dụng C++ được quản lý để truy cập C++ không được quản lý và biên dịch thành một assembly.

+0

Mọi thông tin khác về điều này? Tôi mới vào lập trình Windows, tôi đã quen với Unix, liên kết tĩnh và Makefiles ... Làm thế nào để tạo một DLL được quản lý hoặc DLL không được quản lý với C++ trong VS2010? –

+0

@robert http://ondotnet.com/pub/a/dotnet/2004/03/29/mcpp_part3.html – 0x4f3759df

+0

@robert liên kết ở trên cho thấy cú pháp C++ cũ đã lỗi thời được quản lý, '__gc' trở thành' ref' trong cú pháp hiện đại chẳng hạn. – jdehaan

2

Tôi tin rằng bạn có thể gọi hàm bên trong khối "C" bên ngoài từ C# theo số chỉ tham chiếu đến DLL.

Sai, bạn phải sử dụng DllImport hoặc gọi là PInvoke (Gọi nền tảng) để gọi hàm C gốc từ mã được quản lý. Tham chiếu chỉ hoạt động đối với các hội đồng .NET hoặc COM với automatically generated interop dll.

Sử dụng C++ từ C# trở thành một cơn ác mộng thực sự vì tên mangling trong số những thứ khác.

Nếu bạn có thể bạn có thể biên dịch một Dll C++ được quản lý dưới dạng trình bao bọc để làm cho cả hai thế giới gặp nhau. Điều này cũng có lợi thế mà bạn có thể đánh dấu lắp ráp của bạn là ComVisible, do đó làm cho nó có sẵn cho nhiều công cụ có khả năng xử lý COM.

Cách khác là viết trình bao bọc C quanh API C++, điều gì có thể tẻ nhạt và xấu xí.

EDIT:

Trợ giúp để quyết định phương pháp sử dụng:

  • 1) Bạn có một C dll bản địa
    • Chú ý: nếu bạn sử dụng một lib từ Managed C++, sau đó dll là không đúng sự thật liên kết động và không thể được thay thế bằng một thả đơn giản trong một phiên bản tương thích mới hơn.
    • ƯA THÍCH: Sử dụng P/Invoke từ bất kỳ ngôn ngữ .NET (drop-in thay thế có thể)

  • 2) Bạn có một bản ngữ C++ dll
    • KHÔNG sử dụng P/Gọi, đây là một cơn ác mộng thực sự (vì tên mangling trong số những thứ khác)
    • PREFERRED: Xây dựng một gói .NET dll với C++ được quản lý, chỉ hoạt động nếu bạn có trình biên dịch tương thích với trình biên dịch được sử dụng để biên dịch tệp gốc.
    • Nếu DLL gốc được tạo bằng trình biên dịch không tương thích (Trình biên dịch A) của trình biên dịch C++ (Trình biên dịch C), thì tôi khuyên bạn nên xây dựng (Với cùng trình biên dịch A) một trình bao bọc C quanh C++ gốc dll. Sau đó sử dụng P/Invoke phương pháp sử dụng điều này wrapper C dll như được mô tả trong 1)
+0

cảm ơn cho sự điều chỉnh. bạn có thể tạo một assembly .NET với C++ không? –

+0

Có, nhưng với Managed C++ không thực sự là C++ nhưng sẽ cho phép bạn liên kết với C++ DLL gốc nếu bạn sử dụng trình biên dịch giống với các trình tạo dll C++ thuần túy mà bạn đang sử dụng. – jdehaan

+0

P/Gọi là không vui vẻ – 0x4f3759df

1

gì DLL không nội là không thích hợp, như xa như C# là có liên quan. Hãy nhớ rằng các mẫu C++ không tạo ra bất kỳ mã nào cho đến khi mẫu được khởi tạo. Nếu mẫu được định nghĩa đơn giản ở đâu đó trong các tệp tiêu đề DLL, thì sẽ không có bất kỳ mã được tạo nào cho mẫu đó trong tệp DLL. Mặt khác, nếu DLL một cách rõ ràng instantiates và xuất khẩu một số loại templated, sau đó bạn về mặt lý thuyết có thể gọi chúng từ C#.

Có hai vấn đề bạn phải khắc phục. Đầu tiên là các trình biên dịch C++ mangle tên phương thức của chúng, vì vậy bạn phải tìm ra chính xác tên của PInvoke là gì. Vấn đề thứ hai là không có cách nào để tạo các đối tượng CRT trong C# trực tiếp. Bạn sẽ phải xác định một số phương thức nhà máy và xuất các phương thức đó.

Thành thật mà nói, tôi nghĩ rằng đây là tất cả các cách rắc rối hơn giá trị của nó. Bạn nên tạo một API kiểu C cho DLL và gọi những hàm đó từ C#. Bên trong, các hàm có thể tạo và thao tác các đối tượng C++ có liên quan.

+0

OK, nghe có vẻ như một cơn đau khổng lồ. Tạo một API C là một giải pháp công bằng, nhưng tôi ngạc nhiên không có một cơ chế interop linh hoạt hơn ... –

+1

Cơ chế interop sẽ phải xử lý tất cả các lược đồ có thể mang lại cho bất kỳ trình biên dịch nào vì không có tiêu chuẩn cho điều này (đó là một nỗi đau lớn) và marshalling/unmarshalling không phải là tầm thường. Trong trường hợp của COM tất cả mọi thứ được chỉ định trong giao diện và các loại được xác định rõ về kích thước và sự liên kết. – jdehaan

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