2011-12-01 21 views
7

que estoy recibiendo este error:E2010 Tipos incompatibles, ¿por qué?

[DCC Error] JwaStrSafe.pas(2277): E2010 Incompatible types: 'PSTRSAFE_LPWSTR' and 'PSTRSAFE_LPTSTR' 

La siguiente es la parte relevante del código de JwaStrSafe.pas (de Jedi Api), estoy compilando con el símbolo definido UNICODE:

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} 

Aparece el error en la llamada de StringCchCopyExW, en el parámetro ppszDestEnd.

Viendo la definición del tipo Entiendo que PSTRSAFE_LPTSTR es un tipo de puntero a STRSAFE_LPTSTR que es solo un alias de STRSAFE_LPWSTR, ¿por qué son incompatibles PSTRSAFE_LPTSTR y PSTRSAFE_LPWSTR?

Solución
Gracias a la explicación de David I reemplazados

PSTRSAFE_LPTSTR = ^STRSAFE_LPTSTR; 

con

PSTRSAFE_LPTSTR = PSTRSAFE_LPWSTR; 

ahora el código se compila sin errores.

Gracias

+2

¿Qué versión de Delphi estás usando? –

+0

Uso de Delphi XE2 –

Respuesta

3

que pueden reproducir esta bastante facilidad en XE2, y me imagino que se va a comportar el mismo en todas las demás versiones. Para hacerlo más simple lo he reducido a esto:

program PointerTypeCompatibility; 
{$APPTYPE CONSOLE} 
type 
    A = Integer; 
    B = Integer; 
var 
    ptA: ^A; 
    ptB: ^B; 
begin 
    ptA := ptB; 
end. 

Esto también produce E2010. Sin embargo, si habilita la opción type-checked pointers, el código se compila correctamente. De hecho, la documentación de las opciones del compilador que afirma:

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.


Gracias a Ken White para señalarme en el tema de ayuda útil Type Compatibility and Identity. Los extractos pertinentes son que los tipos T1 y T2 son asignación compatibles si:

T1 and T2 are compatible pointer types.

La documentación también establece que los tipos son tipo compatibile si:

Both types are (typed) pointers to the same type and the {$T+} compiler directive is in effect.

Así que este documenta el comportamiento observado y me lleva a este ejemplo:

program PointerTypeCompatibilityTake2; 
{$APPTYPE CONSOLE} 
{$TYPEDADDRESS OFF} 
var 
    P1,P2: ^Integer; 
    P3: ^Integer; 
begin 
    P1 := P2;//compiles 
    P1 := P3;//E2008 Incompatible types 
end. 

Así que, en resumen:

  • Cuando los punteros de verificación de tipo están deshabilitados, los punteros son compatibles con la asignación si los punteros son del mismo tipo.
  • Cuando los punteros de verificación de tipo están habilitados, los punteros son compatibles con la asignación si los punteros apuntan al mismo tipo.

Tengo que confesar que ignoro el historial y el razonamiento detrás de la configuración del puntero de verificación de tipo, por lo que no puedo ofrecer ninguna explicación de por qué el compilador es como es.

+3

Esto podría ayudar: [Identidad de tipo] (http://docwiki.embarcadero.com/RADStudio/es/Type_Compatibility_and_Identity). –

+0

@Ken ¡Gracias, eso ayudó mucho! –

+0

De nada. Ya habrías puesto tanto trabajo sin el enlace; No quería usarlo y robar tu trabajo. :) Buen trabajo - +1. –

Cuestiones relacionadas