2013-03-24 73 views
5

Tôi đang trong quá trình gói một dự án VC++ 9 không được quản lý trong C++/CLI để sử dụng nó rõ ràng từ một ứng dụng .NET. Tôi biết làm thế nào để viết wrappers, và rằng mã không được quản lý can be executed from .NET, nhưng những gì tôi có thể không hoàn toàn quấn quanh đầu tôi:Có thể chạy C++ không được quản lý bình thường từ một dự án C++/CLI được quản lý không?

  1. Các lib không được quản lý là một C rất phức tạp ++ thư viện và sử dụng rất nhiều nội tuyến và khác các tính năng, vì vậy tôi không thể biên dịch điều này thành /clr -marked managed DLL. Tôi cần phải biên dịch này thành một DLL riêng biệt bằng cách sử dụng trình biên dịch VC++ bình thường.

  2. Làm cách nào để xuất các ký hiệu từ mã không được quản lý này để mã có thể được sử dụng từ dự án C++/CLI? Tôi có đánh dấu mọi lớp tôi cần hiển thị là extern không? Nó đơn giản hay có một số phức tạp hơn?

  3. Làm cách nào để truy cập các ký hiệu đã xuất từ ​​dự án C++/CLI? Tôi chỉ cần bao gồm các tệp tiêu đề của mã nguồn không được quản lý và trình liên kết C++ có lấy mã thực tế từ DLL không được quản lý không? Hoặc tôi có phải viết tay một bộ riêng biệt của "extern" các lớp học trong một tập tin tiêu đề mới trỏ đến các lớp học trong DLL?

  4. Khi dự án C++/CLI của tôi tạo các lớp không được quản lý, mã không được quản lý có chạy hoàn toàn tốt trong thời gian chạy VC9 bình thường hay nó sẽ bị buộc phải chạy trong .NET? gây ra vấn đề tương thích nhiều hơn? Dự án C++ tạo ra nhiều trường hợp và có trình thu gom rác được thực hiện tùy chỉnh của riêng mình, tất cả được viết bằng đồng bằng C++, nó là trình kết xuất âm thanh DirectX và quản lý rất nhiều đối tượng DirectX. Tất cả điều này có hoạt động bình thường hoặc chức năng Win32 như vậy có bị ảnh hưởng theo bất kỳ cách nào không?

+2

Có, bạn có thể thực hiện chế độ hỗn hợp. Chỉ cần đánh dấu các tập tin bạn muốn biên dịch như là bản địa, không có tùy chọn '/ clr'. Có một số chỉ thị #pragma để kiểm soát điều này ở cấp chức năng. – leppie

Trả lời

7

Bạn có thể bắt đầu với một ++ Dự án thông thường có nguồn gốc C (nhập khẩu từ, nói, Visual Studio 6.0 từ hơn một thập kỷ trước) và khi bạn xây dựng nó ngày hôm nay, nó sẽ liên kết đến phiên bản hiện tại của thời gian chạy VC.

Sau đó, bạn có thể thêm một tệp mới foo.cpp vào đó, nhưng định cấu hình tệp đó để tệp có cờ/CLR được bật. Điều này sẽ làm cho trình biên dịch tạo ra IL từ một tệp đó và cũng liên kết trong một số hỗ trợ bổ sung làm cho khuôn khổ .NET được nạp vào trong quá trình khi nó khởi động, vì vậy nó có thể biên dịch JIT và sau đó thực thi IL.

Phần còn lại của ứng dụng vẫn được biên dịch nguyên bản như trước đây và hoàn toàn không bị ảnh hưởng.

Sự thật là ngay cả một ứng dụng CLR "thuần túy" thực sự là một lai, vì bản thân CLR là mã gốc (rõ ràng). Một ứng dụng hỗn hợp C++/CLI chỉ mở rộng điều này bằng cách cho phép bạn thêm nhiều mã gốc hơn mà chia sẻ quy trình với một số mã được lưu trữ CLR. Chúng cùng tồn tại trong suốt thời gian của quá trình.

Nếu bạn thực hiện một tiêu đề foo.h với một tuyên bố:

void bar(int a, int b); 

Bạn có thể tự do thực hiện hoặc gọi đây là một trong hai trong mã nguồn gốc của bạn hoặc trong các mã foo.cpp CLR. Trình biên dịch/liên kết kết hợp sẽ chăm sóc mọi thứ. Không cần phải làm bất kỳ điều gì để gọi vào mã gốc từ bên trong mã CLR của bạn.

Bạn có thể được biên dịch lỗi về công tắc không tương thích:

  • /ZI - cơ sở dữ liệu Chương trình chỉnh sửa và tiếp tục, thay đổi nó để chỉ Chương trình cơ sở dữ liệu
  • /Gm - bạn cần phải vô hiệu hóa tối thiểu xây dựng lại
  • /EHsc - ngoại lệ C++, đổi thành Có với ngoại lệ SEH (/ EHa)
  • /RTC - Thời gian chạy kiểm tra, thay đổi nó để Mặc định
  • tiêu đề biên dịch sẵn - thay đổi nó để Không dùng precompiled Headers
  • /GR- - Runtime Loại thông tin - thay đổi nó để On (/ GR)

Tất cả những thay đổi này chỉ cần được thực hiện đối với các tệp được bật/CLR cụ thể của bạn.

+0

TUYỆT VỜI! Nhưng làm cách nào để đánh dấu '/ clr' chỉ cho một tệp? Tôi có phải bật '/ clr' cho toàn bộ dự án trong hộp thoại Thiết lập Dự án không? –

+0

Không, chỉ cần đưa lên các thuộc tính cho foo.cpp, đi đến phần C++, và cho cài đặt * Ngôn ngữ chung Hỗ trợ RunTime * chọn * Ngôn ngữ chung Hỗ trợ RunTime (/ clr) * –

+0

Sau đó bạn có thể nhận được một số lỗi cho bạn biết rằng các tùy chọn khác cần được tắt - sẽ cập nhật. –

0

Bạn có thể sử dụng PInvoke để gọi các hàm được xuất từ ​​các tệp DLL không được quản lý. Đây là cách Windows API không được quản lý được truy cập từ .Net. Tuy nhiên, bạn có thể gặp sự cố nếu các hàm được xuất của bạn sử dụng các đối tượng C++ và không chỉ là các cấu trúc dữ liệu C thuần túy.

Ngoài ra còn có vẻ là C++ công nghệ Interop có thể được sử dụng cho bạn: http://msdn.microsoft.com/en-us/library/2x8kf7zx(v=vs.80).aspx

+0

Tôi không nghĩ mình có thể làm được.Tôi đã đề cập trong # 5 rằng thư viện rất phức tạp và quản lý các đối tượng riêng của nó, nó duy trì các đối tượng DirectX đang hoạt động và mọi thứ. Nó thậm chí có GC riêng của mình chạy theo định kỳ. Tôi đang cố gắng để bọc này mà không vi phạm bất cứ điều gì. –

+0

Nếu tôi tạo các hàm tĩnh (tôi có thể), và sử dụng P/Invoke, dự án C++ thực tế có chạy trong môi trường VC++ bình thường hay .NET đơn giản gọi nó trong suốt thời gian của hàm và sau đó tắt nó? –

+0

NB rõ ràng p/gọi là không cần thiết trong C + +/CLI - nó đã được xây dựng trong interop liền mạch ở mức độ chức năng cá nhân. –

1

Như đã đề cập từ Daniel, bạn có thể tinh chỉnh cài đặt của mình ở cấp tệp. Bạn cũng có thể chơi với '#pragma managed' bên trong các tệp, nhưng tôi sẽ không làm điều đó mà không có lý do.

Hãy nhớ rằng bạn có thể tạo một cụm chế độ hỗn hợp hoàn chỉnh. Điều đó có nghĩa, bạn có thể biên dịch mã gốc của bạn không thay đổi thành tệp này. PLUS một số trình bao bọc C++/CLI xung quanh mã này. Cuối cùng, bạn sẽ có cùng một tệp với Dll gốc với tất cả các biểu tượng gốc đã xuất của bạn VÀ là một assembly .NET chính thức (phơi bày các đối tượng C++/CLI) cùng một lúc!

Điều đó cũng có nghĩa là, bạn chỉ quan tâm đến xuất khẩu theo như mã máy khách gốc bên ngoài tệp của bạn được xem xét. Mã C++/CLI của bạn bên trong dll/assembly hỗn hợp có thể truy cập vào cấu trúc dữ liệu nguyên gốc bằng cách sử dụng các quy tắc truy cập thông thường (được cung cấp đơn giản bằng cách đưa vào tiêu đề)

Vì bạn đã đề cập đến nó, tôi đã làm điều này cho một số lớp C++ không tầm thường hệ thống phân cấp bao gồm một số tiền hợp lý của mã DirectX. Vì vậy, không có vấn đề chính ở đây.

Tôi khuyên bạn không nên sử dụng pInvoke trong môi trường .NET. Đúng, nó hoạt động. Nhưng đối với bất cứ điều gì không tầm thường (nói nhiều hơn 10 hàm), bạn chắc chắn là tốt hơn với cách tiếp cận OO như được cung cấp bởi C++/CLI. Các nhà phát triển ứng dụng khách C# của bạn sẽ biết ơn. Bạn có tất cả các công cụ .NET như đại biểu/thuộc tính, quản lý luồng và nhiều hơn nữa trên đầu ngón tay của bạn trong C++/CLI. Bắt đầu với VS 2012 với một phần mềm Intellisense có thể sử dụng được.

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