2009-03-03 47 views
17

Làm thế nào tôi có thể vượt qua một char * từ C dll để VBLàm thế nào để chuyển đổi char * sang BSTR?

Đây là mẫu mã:

void Cfunc(char *buffer,int len) 
{ 
    BSTR buf_bstr = SysAllocString((BSTR)buffer); 
    VBptr.VBfunc(buf_bstr,len); 
} 

Chức năng này không hoạt động, Trong thực tế một số giá trị khác được gửi đến VB chứ không phải là thực tế giá trị.

Có ai vui lòng đề xuất giải pháp không?

+0

Bạn có thể đưa ra ví dụ về chuỗi gốc so với giá trị sai đang được gửi không? –

+0

Vấn đề (ban đầu) của bạn có vẻ là chiều rộng ký tự. BSTR luôn là ký tự rộng (COM là tất cả Unicode). Một diễn viên sẽ không tự động mở rộng các ký tự, nhưng giải thích các byte là wchar_t *. – Richard

+0

Mã giả này có rò rỉ bộ nhớ. Bạn gọi SysAllocString(), nhưng không deallocate chuỗi sau khi bạn không còn cần nó. – sharptooth

Trả lời

18

Sử dụng _bstr_t:

_bstr_t bstrt(buffer); 

Đây là holy grail of string conversion articles

+0

_bstr_t là một lớp học. Không hữu ích cho tinh khiết C, tôi giả sử. – sharptooth

+0

Có u r đúng. Cảm ơn –

+0

Liên kết tuyệt vời, cảm ơn! – Colen

2

tôi không có bất kỳ phản đối ajryan câu trả lời, nhưng đây là một sự thay thế ...

SysAllocString được xác định để có một tham số của loại OLECHAR *. Bạn đang cho nó một char *. Đây không phải là điều tương tự. Có một số trường hợp nhất định khi chúng có thể là giống nhau, nhưng bạn không thể phụ thuộc vào nó. Vì vậy, trước hết bạn cần phải chuyển đổi char * của bạn thành một OLECHAR *. Có một macro gọi là A2OLE có thể làm điều này cho bạn, và trong những trường hợp mà char * và OLECHAR * giống nhau, macro biên dịch thành không có gì (tôi nghĩ).

Xem this page để biết chi tiết về A2OLE và bạn bè của nó.

Ồ, và truyền char * của bạn đến BSTR không thực sự thay đổi nó, nó không phải là BSTR cũng như OLECHAR *.

+0

Btw, đúc WCHAR * vào BSTR cũng là một ý tưởng tồi nếu chuỗi chưa được phân bổ với một trong các hàm gia đình SysAllocString(). Làm như vậy có thể gây ra sự cố nếu cuộc gọi bạn vượt qua các lệnh gọi giả BSTR như vậy SysStringLen() trên đó. – sharptooth

21

Gọi MultiByteToWideChar(), sau đó chọn SysAllocString() hoặc SysAllocStringLen().

Đừng quên gọi SysFreeString() khi bạn không còn cần BSTR nữa.

Cụ thể (SysAllocStringLen() biến thể - đó là ngắn hơn và nhanh hơn):

  1. Gọi MultiByteToWideChar() và vượt qua 0 như tham số thứ năm và thứ sáu. Nó sẽ trả về số ký tự trong Unicode tương đương với chuỗi ANSI. Hãy nhớ rằng, chuỗi ANSI có thể chứa bất kỳ ký tự nào, không chỉ ASCII, vì vậy mọi nỗ lực tính toán số ký tự Unicode theo cách thủ công cho độ dài chuỗi ANSI có thể hoạt động trong một số trường hợp và không hoạt động trong các trường hợp khác.

  2. Phân bổ bộ đệm cho BSTR bằng SysAllocStringLen(). Truyền 0 làm tham số đầu tiên và số ký tự Unicode làm tham số thứ hai. Bây giờ bạn có một BSTR được phân bổ đúng nhưng chưa được khởi tạo. Nó đã có vị trí cho dấu 0 và dấu 0 này được đặt đúng.

  3. Gọi MultiByteToWideChar() lần thứ hai và lần này vượt qua BSTR được phân bổ tại đó. Hàm sẽ chuyển đổi chuỗi thành Unicode và sao chép kết quả vào BSTR. Bây giờ bạn có một BSTR được cấp phát một cách có chứa Unicode tương đương với chuỗi ANSI của bạn.

  4. Chuyển BSTR vào VB. Thưởng thức.

  5. Gọi SysFreeString() để deallocate BSTR.

+0

Vẫn mã của tôi không hoạt động, tôi đã sửa đổi như thế này. void Cfunc (char * buffer, int len) { BSTR buf_bstr; ULONG cCharacters; nếu (0 == MultiByteToWideChar (0, 0, bộ đệm, cCharacters, buf_bstr, cCharacters)); VBptr.VBfunc (buf_bstr, len); } VB Exe bị lỗi. –

+0

Hi Sharptooth .. i am mới với COM này: ( –

+1

Tôi đã chỉnh sửa câu trả lời để bao gồm một bước từng bước làm thế nào để. – sharptooth

10

Đây là mã tôi đã viết bằng sharptooths câu trả lời

int wslen = MultiByteToWideChar(CP_ACP, 0, str, strlen(str), 0, 0); 
    BSTR bstr = SysAllocStringLen(0, wslen); 
    MultiByteToWideChar(CP_ACP, 0, str, strlen(str), bstr, wslen); 
    // Use bstr here 
    SysFreeString(bstr); 

Lưu ý rằng việc sử dụng -1 cho chiều dài của kết quả chuỗi trong terminator rỗng được đưa vào kết quả

1

thay vì mảng char *, hãy thử mảng _tchar *. Bởi vì Sysallocstring chỉ lấy các ký tự Unicode trong một ứng dụng 32 bit.

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