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

时间:2013-11-08 11:12:01

标签: delphi delphi-7 delphi-xe4

我在Delphi 7中的代码中有以下代码:

 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声明如下

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声明如下

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

2 个答案:

答案 0 :(得分:5)

您应该只使用

var
  objServiceConfig: PQueryServiceConfig;

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

修改

除非您打开了“Typed @ operator”编译器选项({$T+}),否则在Delphi XE4中会产生编译器错误E2010 Incompatible types: 'LPQUERY_SERVICE_CONFIGW' and 'PQueryServiceConfigW'。 所以要么使用该选项,要么只是重新声明这个函数:

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中编译。

答案 1 :(得分:3)

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

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

更重要的是,您应确保已阅读并理解Marco Cantù's whitepaper on the Unicode changes introduced in Delphi 2009。如果你不这样做,看起来你没有,那么你的迁移将导致痛苦和痛苦。


实际上,它比那更复杂。如果Delphi头文件翻译正确,上述内容都是准确的。但事实并非如此。这是错误的。

QueryServiceConfig的声明是:

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

但它应该是:

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

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

很抱歉花了很长时间才到达底部。


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

E2010 Incompatible types: 'LPQUERY_SERVICE_CONFIGW' and 'PQueryServiceConfigW'

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

要理解原因,我们需要了解如何声明这些类型和函数。我已经删除了ANSI声明以保持简单说明:

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-状态下,文档说:

  

在{$ T-}状态中,除指针之外的不同指针类型是不兼容的(即使它们是指向同一类型的指针)。

这解释了编译错误。因为LPQUERY_SERVICE_CONFIGPQueryServiceConfig不同。

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

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;

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