E2010不兼容的类型:Delphi XE4中的“ LPQUERY_SERVICE_CONFIGW”和“ PQueryServiceConfigA”错误

E2010 Incompatible types: 'LPQUERY_SERVICE_CONFIGW' and 'PQueryServiceConfigA' error in Delphi XE4

我在某些功能中在Delphi 7中有以下代码:

1
2
3
4
5
6
7
8
9
10
 var
    objServiceConfig: PQueryServiceConfigA;
    ...
    ...
    objServiceConfig:= AllocMem(anySize);
    ...
    ...
    QueryServiceConfig(hSCService, objServiceConfig, anySize, anySize2)
    .....
    .....

我收到错误消息:E2010 Incompatible types: 'LPQUERY_SERVICE_CONFIGW' and 'PQueryServiceConfigA'

在Delphi 7中,一切工作正常,但将其迁移到Delphi XE4时,出现此错误。

当我将上述声明objServiceConfig: PQueryServiceConfigA;更改为objServiceConfig: LPQUERY_SERVICE_CONFIG;时,它将起作用。 是对的还是我还要做什么?

更新:

在Delphi XE4 WinSvc中,QueryServiceConfig的声明如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function QueryServiceConfig(hService: SC_HANDLE;
  lpServiceConfig: LPQUERY_SERVICE_CONFIG; cbBufSize: DWORD;
  var pcbBytesNeeded: DWORD): BOOL; stdcall;  

{$EXTERNALSYM QueryServiceConfigA}

function QueryServiceConfigA(hService: SC_HANDLE;
  lpServiceConfig: LPQUERY_SERVICE_CONFIGA; cbBufSize: DWORD;
  var pcbBytesNeeded: DWORD): BOOL; stdcall;

{$EXTERNALSYM QueryServiceConfigW}

function QueryServiceConfigW(hService: SC_HANDLE;
  lpServiceConfig: LPQUERY_SERVICE_CONFIGW; cbBufSize: DWORD;
  var pcbBytesNeeded: DWORD): BOOL; stdcall;

在Delphi7,WinSvc中,QueryServiceConfig的声明如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function QueryServiceConfig(hService: SC_HANDLE;
  lpServiceConfig: PQueryServiceConfig; cbBufSize: DWORD;
  var pcbBytesNeeded: DWORD): BOOL; stdcall;

{$EXTERNALSYM QueryServiceConfigA}

function QueryServiceConfigA(hService: SC_HANDLE;
  lpServiceConfig: PQueryServiceConfigA; cbBufSize: DWORD;
  var pcbBytesNeeded: DWORD): BOOL; stdcall;

{$EXTERNALSYM QueryServiceConfigW}

function QueryServiceConfigW(hService: SC_HANDLE;
  lpServiceConfig: PQueryServiceConfigW; cbBufSize: DWORD;
  var pcbBytesNeeded: DWORD): BOOL; stdcall;

这意味着在Delphi 7为PQueryServiceConfig / A / W类型的情况下,第二个参数在Delphi XE4为LPQUERY_SERVICE_CONFIG / A / W类型的情况下


您应该简单地使用

1
2
var
  objServiceConfig: PQueryServiceConfig;

在Delphi 7中被声明为PQueryServiceConfigA(ANSI版本),在Delphi XE4中被声明为PQueryServiceConfigW(Unicode版本)。

编辑:

除非您已打开(Type x @ operator)编译器选项({$T+}),否则在Delphi XE4中会产生编译器错误E2010 Incompatible types: 'LPQUERY_SERVICE_CONFIGW' and 'PQueryServiceConfigW'
因此,要么使用该选项,要么简单地重新声明如下函数:

1
2
3
function QueryServiceConfig(hService: SC_HANDLE; lpServiceConfig: PQueryServiceConfig; cbBufSize: DWORD;
  var pcbBytesNeeded: DWORD): BOOL; stdcall;
  external advapi32 name {$IFDEF UNICODE}'QueryServiceConfigW'{$ELSE}'QueryServiceConfigA'{$ENDIF};

这样,它就可以在Delphi 7和XE4中进行编译。


Delphi XE4支持Unicode,而Delphi 7是ANSI版本。因此QueryServiceConfig映射到XE4上的QueryServiceConfigW,但是映射到D7上的QueryServiceConfigA

要解决此问题(但请参见下文),应将PQueryServiceConfigA替换为PQueryServiceConfig。现在,PQueryServiceConfig将映射到Unicode Delphi中的PQueryServiceConfigW和ANSI Delphi中的PQueryServiceConfigA。而这正是您需要的行为。

更重要的是,您应该确保已阅读并理解MarcoCantù关于Delphi 2009中引入的Unicode更改的白皮书。如果您不这样做,而且看起来好像还没有,那么迁移将导致痛苦。

实际上,它比这更复杂。如果Delphi标头转换正确,则以上内容都是正确的。但事实并非如此。做错了。

QueryServiceConfig的声明为:

1
2
3
function QueryServiceConfig(hService: SC_HANDLE;
  lpServiceConfig: LPQUERY_SERVICE_CONFIG; cbBufSize: DWORD;
  var pcbBytesNeeded: DWORD): BOOL; stdcall;

但是应该是:

1
2
3
function QueryServiceConfig(hService: SC_HANDLE;
  lpServiceConfig: PQueryServiceConfig; cbBufSize: DWORD;
  var pcbBytesNeeded: DWORD): BOOL; stdcall;

因此,您需要将变量声明为LPQUERY_SERVICE_CONFIG类型,以解决该错误。

很抱歉花了这么长时间才了解到这一点。

似乎还有更多的东西。 TOndrej正确指出TYPEDADDRESS编译器指令$T的状态会产生影响。其默认设置为OFF。在这种情况下,将PQueryServiceConfig传递给QueryServiceConfig会导致编译器错误:

1
E2010 Incompatible types: 'LPQUERY_SERVICE_CONFIGW' and 'PQueryServiceConfigW'

如果强烈建议将设置切换为ON,则编译成功。

要了解原因,我们需要查看如何声明这些类型和函数。我删除了ANSI声明以使说明简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
type
  LPQUERY_SERVICE_CONFIGW = ^QUERY_SERVICE_CONFIGW;
  LPQUERY_SERVICE_CONFIG = LPQUERY_SERVICE_CONFIGW;
  QUERY_SERVICE_CONFIGW = record
    ...
  end;
  QUERY_SERVICE_CONFIG = QUERY_SERVICE_CONFIGW;
  _QUERY_SERVICE_CONFIGW = QUERY_SERVICE_CONFIGW;
  PQueryServiceConfigW = ^TQueryServiceConfigW;
  PQueryServiceConfig = PQueryServiceConfigW;
  TQueryServiceConfigW = QUERY_SERVICE_CONFIGW;
  TQueryServiceConfig = TQueryServiceConfigW;

function QueryServiceConfig(... lpServiceConfig: LPQUERY_SERVICE_CONFIG ...

现在,在T-状态下,文档显示:

In the {$T-} state, distinct pointer types other than Pointer are incompatible (even if they are pointers to the same type).

这说明了编译错误。因为LPQUERY_SERVICE_CONFIGPQueryServiceConfig不同。

现在,可以通过这种方式声明类型:

1
2
3
4
5
6
7
8
9
10
11
12
type
  QUERY_SERVICE_CONFIGW = record
  end;
  QUERY_SERVICE_CONFIG = QUERY_SERVICE_CONFIGW;
  _QUERY_SERVICE_CONFIGW = QUERY_SERVICE_CONFIGW;
  TQueryServiceConfigW = QUERY_SERVICE_CONFIGW;
  TQueryServiceConfig = TQueryServiceConfigW;

  LPQUERY_SERVICE_CONFIGW = ^QUERY_SERVICE_CONFIGW;
  LPQUERY_SERVICE_CONFIG = LPQUERY_SERVICE_CONFIGW;
  PQueryServiceConfigW = LPQUERY_SERVICE_CONFIGW;
  PQueryServiceConfig = PQueryServiceConfigW;

然后,您可以将这四种指针类型中的任何一种传递给函数,因为它们实际上都是相同类型的别名。