Tôi có một đối tượng BSTR mà tôi muốn chuyển đổi để sao chép vào một đối tượng wchar__t. Điều khó khăn là độ dài của đối tượng BSTR có thể ở bất cứ đâu từ vài kilobyte đến vài trăm kilobyte. Có cách sao chép dữ liệu hiệu quả không? Tôi biết tôi chỉ có thể tuyên bố một mảng wchar_t và phân phối các dữ liệu tối đa có thể nó sẽ bao giờ cần phải giữ. Tuy nhiên, điều này có nghĩa là phân bổ hàng trăm kilobyte dữ liệu cho một thứ có khả năng chỉ cần vài kilobyte. Bất kỳ đề xuất?Làm thế nào để bạn sao chép hiệu quả BSTR vào wchar_t []?
Trả lời
Đối tượng BSTR chứa tiền tố độ dài, vì vậy việc tìm hiểu độ dài là giá rẻ. Tìm hiểu chiều dài, phân bổ một mảng mới đủ lớn để giữ kết quả, xử lý vào đó và nhớ giải phóng nó khi bạn hoàn thành.
Sử dụng ATL và CStringT thì bạn chỉ có thể sử dụng toán tử gán. Hoặc bạn có thể sử dụng macro USES_CONVERSION, sử dụng phân bổ đống này, vì vậy bạn sẽ chắc chắn rằng bạn sẽ không bị rò rỉ bộ nhớ.
Không bao giờ cần chuyển đổi. Một con trỏ BSTR
trỏ đến ký tự đầu tiên của chuỗi và nó bị vô hiệu. Độ dài được lưu trước ký tự đầu tiên trong bộ nhớ. BSTR
s luôn là Unicode (UTF-16/UCS-2). Đã có một giai đoạn được gọi là 'ANSI BSTR' - có một số tham chiếu trong các API cũ - nhưng bạn có thể bỏ qua chúng trong sự phát triển hiện tại.
Điều này có nghĩa là bạn có thể chuyển số BSTR
an toàn cho bất kỳ chức năng nào mong đợi một số wchar_t
.
Trong Visual Studio 2008, bạn có thể gặp lỗi trình biên dịch vì BSTR
được định nghĩa là con trỏ đến unsigned short
, trong khi wchar_t
là kiểu gốc. Bạn có thể truyền hoặc tắt wchar_t
tuân thủ /Zc:wchar_t
.
Một điều cần ghi nhớ là các chuỗi BSTR
có thể và thường có, chứa các giá trị được nhúng. Một null không có nghĩa là kết thúc của chuỗi.
Trước tiên, bạn có thể không thực sự phải làm gì cả, nếu tất cả những gì bạn cần làm là đọc nội dung. Một kiểu BSTR là một con trỏ tới một mảng wchar_t đã kết thúc bằng null. Trong thực tế, nếu bạn kiểm tra các tiêu đề, bạn sẽ thấy rằng BSTR được về cơ bản định nghĩa là:
typedef BSTR wchar_t*;
Vì vậy, trình biên dịch không thể phân biệt giữa họ, mặc dù họ có ngữ nghĩa khác nhau.
Có hai cảnh báo quan trọng.
BSTRs được cho là không thay đổi. Bạn không bao giờ nên thay đổi nội dung của BSTR sau khi nó đã được khởi tạo. Nếu bạn "thay đổi nó", bạn phải tạo một cái mới gán con trỏ mới và giải phóng con trỏ cũ (nếu bạn sở hữu nó).
[CẬP NHẬT: điều này không đúng; lấy làm tiếc! Bạn có thể sửa đổi BSTRs tại chỗ; Tôi rất hiếm khi có nhu cầu.]BSTR được phép chứa các ký tự null được nhúng, trong khi chuỗi C/C++ truyền thống thì không.
Nếu bạn có một số tiền hợp lý của kiểm soát nguồn gốc của BSTR, và có thể đảm bảo rằng các BSTR không có NULLs nhúng, bạn có thể đọc từ BSTR như thể nó là một wchar_t và sử dụng chuỗi thông thường các phương thức (wcscpy, v.v.) để truy cập nó. Nếu không, cuộc sống của bạn trở nên khó khăn hơn. Bạn sẽ phải luôn thao tác dữ liệu của mình dưới dạng nhiều BSTR hơn hoặc dưới dạng mảng được phân bổ động của wchar_t. Hầu hết các hàm liên quan đến chuỗi sẽ không hoạt động chính xác.
Giả sử bạn kiểm soát dữ liệu của mình hoặc đừng lo lắng về NULL. Giả sử rằng bạn thực sự cần tạo một bản sao và không thể đọc trực tiếp BSTR hiện có. Trong trường hợp đó, bạn có thể làm một cái gì đó như thế này:
UINT length = SysStringLen(myBstr); // Ask COM for the size of the BSTR
wchar_t *myString = new wchar_t[lenght+1]; // Note: SysStringLen doesn't
// include the space needed for the NULL
wcscpy(myString, myBstr); // Or your favorite safer string function
// ...
delete myString; // Done
Nếu bạn đang sử dụng giấy gói lớp cho BSTR của bạn, bao bọc nên có một cách để gọi SysStringLen() cho bạn. Ví dụ:
CComBString use .Length();
_bstr_t use .length();
CẬP NHẬT: Đây là một bài viết tốt về chủ đề bởi một ai đó hơn rất nhiều hiểu biết hơn tôi:
"Eric [Lippert]'s Complete Guide To BSTR Semantics"
CẬP NHẬT: Thay thế strcpy() với wcscpy() trong ví dụ
AFAIK, BSTRs * không * được cho là không thay đổi. Đó là lý do tại sao họ không tuyên bố const *. – Constantin
Hmmm ... Tôi không thể tìm thấy bất kỳ tài liệu tham khảo nào hỗ trợ vị trí của tôi. Tôi đang nghĩ gì vậy? Tôi sẽ sửa nó. –
bạn không nên sử dụng wcscpy thay vì strcpy? – arolson101
- 1. C++: Chuyển đổi wchar_t * thành BSTR?
- 2. Làm thế nào để bạn sao chép một BufferedImage
- 3. Làm thế nào để bạn làm cho bộ nhớ ứng dụng Java của bạn hiệu quả?
- 4. làm thế nào để bạn sao chép một CALayer?
- 5. Làm thế nào để sao chép vào clipboard bằng X11?
- 6. Làm thế nào để sao chép vào clipboard trong F #?
- 7. tĩnh phân tích mã để phát hiện thông qua một wchar_t * để BSTR
- 8. Làm thế nào để sao chép mảng?
- 9. Làm thế nào để sao chép ImageData?
- 10. Làm thế nào để chuyển đổi wchar_t * để const char *
- 11. Làm thế nào để bạn nối hai wchar_t * lại với nhau?
- 12. Bạn sẽ triển khai đuôi hiệu quả như thế nào?
- 13. Làm thế nào để chuyển đổi char * sang BSTR?
- 14. Làm thế nào để bạn tạo hoặc tìm tệp "userdata.img" cho ABI armeabi để sao chép vào thư mục AVD
- 15. Làm thế nào để giữ cho bản sao chỉ có hiệu quả?
- 16. Làm thế nào để đưa AOP vào phát triển phần mềm hiệu quả?
- 17. As3 - Làm thế nào để xóa một mảng hiệu quả?
- 18. Làm thế nào để điều này hiệu quả hơn?
- 19. Làm thế nào để bạn dán linefeeds vào mediawiki?
- 20. Làm thế nào để học OCaml hiệu quả?
- 21. Làm thế nào để bạn theo dõi hiệu quả nợ kỹ thuật?
- 22. Làm thế nào để học cách sử dụng IDE của bạn một cách hiệu quả?
- 23. Làm thế nào để bạn sao chép một tập hợp các tập tin vào nhiều nơi bằng Wix?
- 24. Làm thế nào để bạn sao chép một đối tượng PHP vào một loại đối tượng khác nhau
- 25. Làm thế nào để vô hiệu hóa Emacs Ác lựa chọn tự động sao chép vào clipboard
- 26. Làm thế nào để sao chép/sao chép một môi trường ảo từ máy chủ web
- 27. Cách hiệu quả nhất để sao chép số lượng lớn vào SQL Server từ Java là gì?
- 28. Làm thế nào để bạn sao chép một lớp bằng Python?
- 29. Làm thế nào để sao chép sâu một cây?
- 30. Làm thế nào để sao chép Danh sách để Mảng
wchar_t không được đảm bảo chính xác với kích thước của một đoạn mã ngắn. – ben
Tôi nghĩ hoạt động này luôn an toàn, nhưng có thể không phải lúc nào cũng cho kết quả mong đợi. Một BSTR có thể chứa các ký tự null trong phần thân của nó (do đó tiền tố độ dài), trong khi một hàm mong đợi một wchar_t * sẽ giải thích ký tự null đầu tiên ở cuối chuỗi. – Martin
Bạn không thể "vượt qua một BSTR một cách an toàn cho bất kỳ chức năng mong đợi một wchar_t *". So sánh SysStringLen (NULL) và wcslen (NULL). – Constantin