3

我在 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类型

4

2 回答 2

5

你应该简单地使用

var
  objServiceConfig: PQueryServiceConfig;

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

编辑:

除非您打开了“Typed @ operator”编译器选项 ( ),否则这会在 Delphi XE4 中{$T+}产生编译器错误。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 中编译。

于 2013-11-08T11:22:59.633 回答
4

Delphi XE4 支持Unicode,Delphi 7 是ANSI 版本。所以QueryServiceConfig映射到QueryServiceConfigWXE4,但QueryServiceConfigA在 D7 上。

要解决问题(但见下文),您应该替换PQueryServiceConfigAPQueryServiceConfig. 现在,PQueryServiceConfig将映射到PQueryServiceConfigWUnicode Delphi 和PQueryServiceConfigAANSI Delphi 中。这正是您需要的行为。

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


实际上,它比这更复杂。如果 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。在这种情况下,传递 aPQueryServiceConfigQueryServiceConfig导致编译器错误:

E2010 不兼容的类型:“LPQUERY_SERVICE_CONFIGW”和“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-} 状态下,Pointer 以外的不同指针类型是不兼容的(即使它们是指向同一类型的指针)。

这解释了编译错误。因为LPQUERY_SERVICE_CONFIG区别于PQueryServiceConfig

现在,可以这样声明类型:

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;

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

于 2013-11-08T11:23:30.000 回答