2008-11-12 28 views
17

Tôi đang chuyển đổi các ứng dụng của mình sang Delphi 2009 và gặp phải một vấn đề hấp dẫn với một số cuộc gọi cần chuyển đổi một chuỗi (rộng) thành AnsiString.Chuyển chuỗi thành PAnsiChar ở Delphi 2009

Dưới đây là một ví dụ để chứng minh vấn đề tôi đang gặp:

var 
    s: PAnsiChar; 

... 

s := PAnsiChar(Application.ExeName); 

Với Delphi 2007 và các phiên bản trước, s: = PChar (Application.ExeName) sẽ quay trở lại con đường ứng dụng exe.

với Delphi 2009, s: = PAnsiChar (Application.ExeName) chỉ trả về 'E'.

Tôi đoán là vì tôi đang chuyển đổi chuỗi unicode thành chuỗi ansi nhưng làm cách nào tôi có thể chuyển đổi chuỗi sao cho PAnsiChar nhận được chuỗi đầy đủ?

Trả lời

25

Tôi không có Delphi 2009 ở đây, vì vậy tôi không thể kiểm tra. Nhưng có thể bạn phải thử:

s := PAnsiChar(AnsiString(Application.ExeName)); 

Vì gabr đã chỉ ra, đây không phải là thực hành rất tốt và bạn sẽ chỉ sử dụng nếu bạn chắc chắn 100%. Chuỗi chỉ chứa các ký tự có ánh xạ trực tiếp đến dải ANSI.

Đó là lý do tại sao bạn sẽ nhận được cảnh báo vì bạn đang chuyển đổi Unicode sang ANSI.

+0

Bạn không nên vì nó là một chuyển đổi rõ ràng. Và, có, nó sẽ hoạt động. – gabr

+0

Tôi biết, nhưng việc chuyển đổi sang PAnsiChar cũng là một vấn đề nhỏ. –

+1

Tính năng này hoạt động theo chi phí của chuyển đổi rõ ràng. Có cách nào khác không? Việc chuyển đổi sang PAnsiChar được giải thích trong phần trả lời của tôi dưới đây. – smartins

0

WideCharToMultiByte có thể giúp bạn.

+0

WideCharToMultiByte được sử dụng nội bộ trong một số phôi của Delphi –

1

Chuyển đổi rõ ràng của trò chơi hoạt động. Tôi giải thích vấn đề chi tiết hơn dưới đây để có lẽ ai đó có thể chỉ ra một giải pháp tốt hơn.

Tôi đang sử dụng các chức năng sau đây để lấy ngày nộp đơn biên soạn:

function LinkerTimeStamp(const FileName: string): TDateTime; 
var 
    LI: TLoadedImage; 
begin 
    {$IFDEF UNICODE} 
    Win32Check(MapAndLoad(PAnsiChar(AnsiString(FileName)), nil, @LI, False, True)); 
    {$ELSE} 
    Win32Check(MapAndLoad(PChar(FileName), nil, @LI, False, True)); 
    {$ENDIF} 
    Result := LI.FileHeader.FileHeader.TimeDateStamp/SecsPerDay + UnixDateDelta; 
    UnMapAndLoad(@LI); 
end; 

MapAndLoad đòi hỏi một PAnsiChar cho ImageName Parameter vì vậy tôi cần phải chuyển đổi các chuỗi unicode. Có cách nào khác để chuyển đổi một cách rõ ràng sang AnsiString trước không?

+0

Không có phiên bản Unicode của MapAndLoad? –

+0

Không, tôi không nghĩ có phiên bản Unicode. Đơn vị CodeGear Imagehlp tuyên bố MapAndLoad là một LPSTR ánh xạ tới PAnsiChar. Và không đề cập đến msdn về một phiên bản Unicode. – smartins

+2

Bạn có lẽ nên thêm một bình luận những gì bạn đã thay đổi cho Unicode tương thích, và loại bỏ các IFDEF hoàn toàn - PAnsiChar và AnsiString có sẵn ít nhất trong Delphi 4 đã có, và các typecasts không làm tổn thương trong các chương trình Ansi. Mã đơn giản càng tốt IMHO. – mghie

1

Tôi gặp vấn đề tương tự. PAnsiChar chỉ trỏ đến ký tự đầu tiên. Tôi đã viết hàm sau để xử lý chức năng cũ.

// This function converts a string to a PAnsiChar 
// If the output is not the same, an exception is raised 
// Author: [email protected] 

function StringToPAnsiChar(stringVar : string) : PAnsiChar; 
Var 
    AnsString : AnsiString; 
    InternalError : Boolean; 
begin 
    InternalError := false; 
    Result := ''; 
    try 
    if stringVar <> '' Then 
    begin 
     AnsString := AnsiString(StringVar); 
     Result := PAnsiChar(PAnsiString(AnsString)); 
    end; 
    Except 
    InternalError := true; 
    end; 
    if InternalError or (String(Result) <> stringVar) then 
    begin 
    Raise Exception.Create('Conversion from string to PAnsiChar failed!'); 
    end; 
end; 
+0

'PAnsiChar (AnsiString (stringVar)) 'là tất cả những gì bạn cần. –

+3

Sẽ không có vấn đề với AnsString là biến cục bộ và do đó Kết quả trỏ đến biến đó sẽ không còn khả dụng sau khi thoát khỏi hàm? Nói cách khác, một vi phạm truy cập trong chờ đợi? – dummzeuch

-1

Tôi nghĩ rằng bạn có một chút nghỉ ngơi. Mỗi chức năng API Win32 có một đối tác unicode, nếu nó đang mong đợi một chuỗi. Hãy thử MapAndLoadW thay vì MapAndLoad ...

+0

Không có MapAndLoadW. Đó là điều đầu tiên tôi nhìn. Không phải tất cả các API Win32 đều có các đối tác unicode, nhưng hầu hết các API này đều không có. – smartins

3

Thay vì sử dụng loại String, sử dụng RawByteString:

s: RawByteString; 

s := LoadSomeRegularString(usually a string type); 

PAnsiChar(s) <<< all fine. 
+0

Không, đừng làm vậy. Đó là một sự lạm dụng hoàn toàn của 'RawByteString'. Thay vì làm điều này, hãy đọc tài liệu cho 'RawByteString' và tìm hiểu xem nó thực sự là cái gì. –

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