2016-09-25 36 views
9

Đầu tuần này, Kenny Kerr presented C++/WinRT at CppCon 2016 . Nó là một phép chiếu C++ chuẩn cho Windows Runtime, dựa trên Modern.Có thể sử dụng C++/CX và C++/WinRT trong cùng một dự án không?

Theo tôi hiểu, trình biên dịch/bộ tiền xử lý/bộ mã hóa C++/CX không chạm vào mã C++ chuẩn, và với C++/WinRT là thư viện chuẩn C++, đó là cách giải thích ngây thơ của tôi, cả C++/CX và C++/WinRT có thể được sử dụng trong cùng một dự án.

Câu hỏi:

  • Trước tiên: Liệu giải thích ngây thơ của tôi có đúng không?
  • Nếu có, C++/CX và C++/WinRT có thể được sử dụng trong cùng một đơn vị biên dịch không?
  • Tại mức độ chi tiết nào có thể trộn lẫn C++/CX và C++/WinRT, trong trường hợp chúng không thể nằm trong cùng một đơn vị biên dịch?
  • C++/WinRT có thể tiêu thụ các loại được triển khai bằng C++/CX trong cùng một dự án không? (Tôi mong đợi điều này là khó khăn, vì trình biên dịch C++/WinRT cần tạo ra các tiêu đề từ siêu dữ liệu .winmd, do đó có sự phụ thuộc vào đầu ra trình biên dịch (trước).

Trong trường hợp quan trọng, câu trả lời cho những câu hỏi đó cho phép tôi đưa ra quyết định ngay bây giờ về cách di chuyển các dự án C++/CX của tôi trong tương lai.


Embracing Standard C++ for the Windows Runtime (on YouTube).

+0

Hmya, chúng tôi sẽ phải xem những gì anh ấy đang làm việc trong năm qua, anh ấy đã không lưu giữ kho lưu trữ github của mình được cập nhật. Nếu bạn chưa bao giờ có lý do chính đáng để thâm nhập vào WRL trước đó thì có khả năng C++/WinRT sẽ quay bất kỳ cánh quạt nào. Mà thực sự là những gì nó được, ít nhất là hương vị moderncpp, một wrapper như WRL nhưng cập nhật cho C++ 1xyz. Mã của Kerr và McNellis làm tôi đau đầu, bạn có thể thấy nó làm gì nhưng không dễ dàng thấy nó không làm gì. –

+0

@HansPassant: Lý do chính cho C++/WinRT (trên C++/CX) sẽ là hiệu suất. Thời gian biên dịch không phải là tuyệt vời, và thông báo lỗi là câu đố tốt, thường là. Tuy nhiên, tôi thích cú pháp ngắn gọn (hoặc quá ngắn gọn, nếu bạn muốn) nhiều hơn lời gọi WRL rõ ràng (tôi có thể thay đổi suy nghĩ của mình, lần đầu tiên tôi phải gỡ lỗi một vấn đề thực). Tôi đồng ý, rằng khó thấy hơn, mã nào (hoặc không làm). Nhưng điều đó cũng đúng với C# /. NET, và điều đó không bao giờ là cách làm cho nó trở thành mục tiêu ưa thích cho nhiều người ở ngoài kia. Dù sao, sở thích cá nhân là cá nhân, tôi đoán;) – IInspectable

+0

Tôi không phải là một chuyên gia C++, nhưng ... tại sao không? Các dự án C++/CX có thể có mã C++ thông thường trong đó và C++/WinRT chỉ là C++ thông thường, đúng không? –

Trả lời

2

Về câu hỏi "C++/WinRT có thể sử dụng các loại được triển khai với C++/CX trong cùng một dự án không?"

Câu trả lời là Có và Không.Với một 'lớp ref' được định nghĩa trong cùng một dự án, như một dự án phải được biên dịch với C++/CX được kích hoạt, mã của bạn có thể sử dụng lớp đơn giản vì nó có thể có bất kỳ lớp ref nào.

Tuy nhiên, nếu bạn muốn sử dụng 'lớp ref' làm phép chiếu C++/WinRT, câu trả lời là không có hiệu quả.

Để lấy định nghĩa lớp dự đoán C++/WinRT, bạn cần chạy trình biên dịch cppwinrt.exe qua siêu dữ liệu cho 'lớp ref'. Điều đó sẽ yêu cầu bằng cách nào đó nhận được siêu dữ liệu. Bạn có thể sắp xếp một số cơ chế để biên dịch 'lớp ref' một lần, lấy winmd, xử lý nó thông qua mdmerge để đặt nó ở dạng chuẩn, chạy cppwinrt.exe trên siêu dữ liệu để lấy định nghĩa lớp dự kiến, sau đó bao gồm các tiêu đề được tạo ra.

Hoặc, bạn có thể viết IDL để mô tả 'lớp ref', biên dịch nó thành siêu dữ liệu bằng MIDLRT, sau đó chạy cppwinrt.exe. IMO không thực tế.

Cách thay thế hợp lý nhất chỉ đơn giản là sử dụng lớp ref như là kiểu C++/CX, vì định nghĩa nằm trong cùng một giải pháp. Giải pháp thực tế nhất tiếp theo là đưa lớp vào một dự án riêng biệt, biên dịch nó thành winmd, sau đó tạo tiêu đề từ winmd. Cách tiếp cận này cũng cho phép dự án riêng biệt tiêu thụ 'lớp ref' (thông qua phép chiếu) để xây dựng mà không cần sử dụng mã C++/CX.

Để hoàn toàn minh bạch, lưu ý rằng bản phát hành ban đầu của chúng tôi (hiện có sẵn tại https://github.com/Microsoft/cppwinrt) không bao gồm trình biên dịch cppwinrt.exe. Thay vào đó, nó chứa các tệp tiêu đề C++/WinRT chứa các dự đoán cho tất cả các kiểu/API Windows Runtime được định nghĩa trong SDK cập nhật kỷ niệm Windows 10 - bao gồm API nền tảng chung và tất cả API SDK mở rộng.

+0

Đó là một bản tóm tắt tuyệt vời, cảm ơn vì điều đó. Đó là cách tôi đã tìm ra. Ngoại trừ, tôi đã hoàn toàn bỏ lỡ sự kiện (hiển nhiên), bạn có thể đơn giản tiêu thụ 'lớp ref' bằng cách sử dụng các phần mở rộng ngôn ngữ C++/CX nếu không mã C++ chuẩn (ví dụ C++/WinRT). Và trong khi bạn gợi ý về nó: Sẽ sớm như thế nào * "sớm" *? Có vẻ như tôi đã mất ngủ trong hơn một năm nay rồi. Không có trình biên dịch lên phía trước là một chút của một let-down, mặc dù tôi hiểu rằng bạn cần phải làm cho nó ngay lần đầu tiên. – IInspectable

+0

Để C++/WinRT tiêu thụ các loại C++/CX, hãy thử áp dụng https://gist.github.com/kennykerr/105f96d61f51b5773670844edec99d85 bây giờ. :) –

10

Câu trả lời ngắn gọn là có thể sử dụng C++/CX và C++/WinRT trong cùng một dự án.

Trình biên dịch C++/CX đưa các loại Winmd vào không gian tên gốc. C++/WinRT kết thúc mọi thứ bên trong không gian tên root winrt riêng của nó để chứa interop với C++/CX và tránh các lỗi không rõ ràng của trình biên dịch C++ với các thư viện khác. Vì vậy, các mã C++/CX sau:

using namespace Windows::Foundation; 
using namespace Windows::Networking; 

Uri^uri = ref new Uri(L"https://moderncpp.com/"); 
HostName^name = ref new HostName(L"moderncpp.com"); 

Có thể được viết lại với C++/WinRT như sau:

using namespace winrt; 
using namespace Windows::Foundation; 
using namespace Windows::Networking; 

Uri uri(L"https://moderncpp.com/"); 
HostName name(L"moderncpp.com"); 

Ngoài ra, nếu bạn đang biên soạn với/ZW thì bạn có thể viết lại như sau (để tránh C2872 lỗi: 'Windows': biểu tượng mơ hồ):

using namespace winrt::Windows::Foundation; 
using namespace winrt::Windows::Networking; 

Uri uri(L"https://moderncpp.com/"); 
HostName name(L"moderncpp.com"); 

một cách khác bạn có thể kết hợp cả hai C++/CX và C++/WinRT trong file cùng một nguồn là sử dụng một không gian tên gốc cho cả hai như sau:

namespace cx 
{ 
    using namespace Windows::Foundation; 
    using namespace Windows::Networking; 
} 

namespace winrt 
{ 
    using namespace Windows::Foundation; 
    using namespace Windows::Networking; 
} 

void Sample() 
{ 
    cx::Uri uri(L"https://moderncpp.com/"); 
    winrt::HostName name(L"moderncpp.com"); 
} 

Vào cuối ngày, C++/WinRT chỉ là một thư viện C++ chuẩn mà bạn có thể đưa vào bất kỳ dự án C++ áp dụng nào. Tuy nhiên, C++/CX và C++/WinRT lại xử lý siêu dữ liệu rất khác nhau. C++/CX đều tiêu thụ và tạo ra siêu dữ liệu trực tiếp trong khi C++/WinRT bị ràng buộc bởi chuẩn C++ và do đó yêu cầu một công cụ độc lập (cppwinrt.exe) để hỗ trợ việc bắc cầu khoảng trống đó.

+0

Cảm ơn bạn rất nhiều vì đã trả lời. Vì vậy, ở cấp nguồn, cả C++/CX và C++/WinRT đều có thể cùng tồn tại trong cùng một đơn vị biên dịch. Tuy nhiên, công cụ không đồng nhất có thể yêu cầu tách biệt (khi người tiêu dùng và người sản xuất sống trong các dự đoán ngôn ngữ khác nhau). Một chi tiết không rõ ràng với tôi, mặc dù: * cppwinrt.exe * có thể trích xuất .winmd siêu dữ liệu từ nguồn C++/WinRT hoặc mã đối tượng? Hoặc có các yêu cầu bổ sung (như các tệp MIDL) để xuất bản các triển khai C++/WinRT cho việc tiêu thụ bằng các phép chiếu ngôn ngữ khác không? – IInspectable

+0

Chúng có thể cùng tồn tại, nhưng cần lưu ý rằng một số tiêu đề hệ thống/tiện ích cụ thể thay đổi hành vi khi được xây dựng bằng ''/ZW'' thay vì không có, và một số tiêu đề yêu cầu nó.Điều này cũng có thể dẫn đến các cảnh báo trình biên dịch bổ sung không xảy ra nếu bạn đang sử dụng C++/WinRT mà không có ''/ZW''. –

+0

Có vẻ như để trả lời các câu hỏi của OP,/ZW không thể hiện diện và vắng mặt trong cùng một đơn vị biên dịch. Do đó, đối với các cấu trúc C++ chuẩn, độ chi tiết nhỏ nhất cho C++/CX và C++/WinRT để cùng tồn tại trong cùng một dự án là trong các đơn vị biên dịch khác nhau trong cùng một đơn vị liên kết (ví dụ: DLL; EXE). Nhưng đối với các cấu trúc .NET, cách duy nhất để cùng tồn tại là thông qua C++/CX (và C#) và trình bày C++/WinRT của các cấu trúc .NET đó. •• hoàn toàn không •• bỏ qua hậu trường thông qua miền C++ chuẩn. – optikos

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