使用winsvc.h中的SERVICE_TABLE_ENTRY避免编译器警告的正确类型转换是什么

时间:2012-01-10 18:03:27

标签: c windows-services

尝试使用以下示例设置SERVICE_TABLE_ENTRY时 Creating Windows service without Visual Studio 并使用Fedora 14上的mingw32交叉编译器进行编译,我收到编译器警告。

我可以制作样本的最短时间是

#include <stdio.h>
#include <windows.h>
#include <winsvc.h>

#define MY_SVC_NAME "My Service"

int cont_running = 1;

DWORD WINAPI ServiceHandlerProc(DWORD ControlCode, DWORD a, void *b, void *c)
{
  switch (ControlCode)
    {
    case SERVICE_CONTROL_STOP : ;
      cont_running = 0;
    }

  return 0;

}

void WINAPI ServiceMain(int argc, char *argv[], char *envp[])
{
  int hServiceStatus;
  hServiceStatus = RegisterServiceCtrlHandlerEx(MY_SVC_NAME, ServiceHandlerProc, 0);
}

int main(int argc, char *argv[], char *envp[])
{
  SERVICE_TABLE_ENTRY ServiceStartTable[] =
  {
    { MY_SVC_NAME, ServiceMain },
    { 0, 0 }
  };

}

但是编译器抱怨MY_SVC_NAME是错误的类型。

$ /usr/bin/i686-pc-mingw32-gcc -o /tmp/test ~/c/sample.c 
sample.c: In function 'main':
sample.c:31:9: warning: initialization from incompatible pointer type

我尝试过分配变量并使用LPSTR LPWSTR char *和char []类型,并尝试在花括号内转换类型,但它不起作用。

查看/usr/i686-pc-mingw32/sys-root/mingw/include/winsvc.h我看到它被定义为

typedef struct _SERVICE_TABLE_ENTRYA {
    LPSTR lpServiceName;
    LPSERVICE_MAIN_FUNCTIONA lpServiceProc;
} SERVICE_TABLE_ENTRYA,*LPSERVICE_TABLE_ENTRYA;
typedef struct _SERVICE_TABLE_ENTRYW {
    LPWSTR lpServiceName;
    LPSERVICE_MAIN_FUNCTIONW lpServiceProc;
} SERVICE_TABLE_ENTRYW,*LPSERVICE_TABLE_ENTRYW;
...
typedef SERVICE_TABLE_ENTRYW SERVICE_TABLE_ENTRY,*LPSERVICE_TABLE_ENTRY;
...
typedef SERVICE_TABLE_ENTRYA SERVICE_TABLE_ENTRY,*LPSERVICE_TABLE_ENTRY;

所以肯定使用

LPSTR my_svc=MY_SVC_NAME;
  SERVICE_TABLE_ENTRY ServiceStartTable[] =
  {
    { my_svc, ServiceMain },
    { 0, 0 }
  };

应该工作???

抱歉,另一个搜索显示了此示例代码 Windows Service C

我将代码更改为

  SERVICE_TABLE_ENTRY ServiceStartTable[2];
  ServiceStartTable[0].lpServiceName = MY_SVC_NAME;
  ServiceStartTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
  ServiceStartTable[1].lpServiceName = NULL;
  ServiceStartTable[1].lpServiceProc = NULL;

现在它编译时没有警告。

1 个答案:

答案 0 :(得分:1)

此信息来自评论:

typedef void (WINAPI LPSERVICE_MAIN_FUNCTIONA)(DWORD,LPSTR);
typedef void (WINAPI LPSERVICE_MAIN_FUNCTIONW)(DWORD,LPWSTR);
typedef LPSERVICE_MAIN_FUNCTIONA LPSERVICE_MAIN_FUNCTION;
typedef LPSERVICE_MAIN_FUNCTIONW LPSERVICE_MAIN_FUNCTION;

(据推测,后两种typedef中只有一种是活跃的。)

LPSERVICE_MAIN_FUNCTION是函数返回void并使用DWORDLPSTRLPWSTR类型的两个参数的typedef。您的ServiceMain函数会返回void并接受类型为intchar**char**三个参数。

更改ServiceMain功能的定义,使其与LPSERVICE_MAIN_FUNCTION兼容。

ServiceMain投射到LPSERVICE_MAIN_FUNCTION会使编译器警告静音,但不会解决问题。这将导致您的函数被称为,就像它被正确声明一样,具有不可预测的结果(未定义的行为)。所有的演员都应该怀疑;如果您的编译器警告您类型不匹配,最好的解决方案通常是更改声明以使类型匹配,而不是强迫编译器假装它们没有问题。

(是否有{1 LPSTRLPWSTR的typedef,具体取决于配置?)