I'm getting this error:
[DCC Error] JwaStrSafe.pas(2277): E2010 Incompatible types: 'PSTRSAFE_LPWSTR' and 'PSTRSAFE_LPTSTR'
The following is the relevant portion of code from JwaStrSafe.pas (from Jedi Api), I'm compiling with the symbol UNICODE defined:
type
STRSAFE_LPWSTR = PWIDECHAR;
PSTRSAFE_LPWSTR = ^STRSAFE_LPWSTR;
{$IFDEF UNICODE}
STRSAFE_LPTSTR = STRSAFE_LPWSTR;
PSTRSAFE_LPTSTR = ^STRSAFE_LPTSTR;
{$ELSE}
...
{$ENDIF}
...
//function declaration
function StringCchCopyExW(
{__out_ecount(cchDest)}pszDest : STRSAFE_LPWSTR;
{__in}cchDest : size_t;
{__in}const pszSrc : STRSAFE_LPCWSTR;
{__deref_opt_out_ecount(pcchRemaining^)}ppszDestEnd : PSTRSAFE_LPWSTR;
{__out_opt}pcchRemaining : PSize_t;
{__in}dwFlags : Cardinal) : HRESULT; stdcall; forward; external;
...
//var passed to function
ppszDestEnd : PSTRSAFE_LPTSTR;
...
{$IFDEF UNICODE}
result := StringCchCopyExW(pszDest, cchDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
{$ELSE}
result := StringCchCopyExA(pszDest, cchDest, pszSrc, ppszDestEnd, pcchRemaining, dwFlags);
{$ENDIF}
I get the error on the call of StringCchCopyExW, on parameter ppszDestEnd.
Looking at the type definition I understand that PSTRSAFE_LPTSTR is a pointer type to STRSAFE_LPTSTR which is just an alias of STRSAFE_LPWSTR, why are PSTRSAFE_LPTSTR and PSTRSAFE_LPWSTR incompatible?
Solution
Thanks to David's explanation I replaced
PSTRSAFE_LPTSTR = ^STRSAFE_LPTSTR;
with
PSTRSAFE_LPTSTR = PSTRSAFE_LPWSTR;
now the code compiles without errors.
Thanks
I can reproduce this easily enough in XE2, and I imagine it will behave the same in all other versions. To make it simpler I've cut it down to this:
program PointerTypeCompatibility;
{$APPTYPE CONSOLE}
type
A = Integer;
B = Integer;
var
ptA: ^A;
ptB: ^B;
begin
ptA := ptB;
end.
This also produces E2010. However, if you enable the type-checked pointers option, then the code compiles successfully. In fact the documentation of that compiler options states:
In the {$T-} state, distinct pointer types other than Pointer are incompatible (even if they are pointers to the same type). In the {$T+} state, pointers to the same type are compatible.
Thanks to Ken White for pointing me at the useful help topic Type Compatibility and Identity. The pertinent extracts are that types T1 and T2 are assignment compatible if:
T1 and T2 are compatible pointer types.
The documentation also states that types are type compatibile if:
Both types are (typed) pointers to the same type and the {$T+} compiler directive is in effect.
So this documents the observed behaviour and leads me to this example:
program PointerTypeCompatibilityTake2;
{$APPTYPE CONSOLE}
{$TYPEDADDRESS OFF}
var
P1,P2: ^Integer;
P3: ^Integer;
begin
P1 := P2;//compiles
P1 := P3;//E2008 Incompatible types
end.
So, to summarise:
I have to confess to being ignorant of the history and reasoning behind the type-checked pointer setting, so I can't offer any explanation for why the compiler is the way it is.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With