Как правильно приводить типы, чтобы избежать предупреждения компилятора с использованием SERVICE_TABLE_ENTRY от winsvc.h - PullRequest
0 голосов
/ 10 января 2012

При попытке установить SERVICE_TABLE_ENTRY, используя пример на Создание службы Windows без Visual Studio и компиляция с использованием кросс-компилятора mingw32 в Fedora 14, я получаю предупреждение компилятора.

Самое короткоеЯ могу сделать пример:

#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 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 Ответ

1 голос
/ 11 января 2012

Информация из комментариев:

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;

(Предположительно, будет активен только один из последних двух типов определений).

LPSERVICE_MAIN_FUNCTION - это typedef для функции, возвращающей void и принимающей два аргумента типов DWORD и LPSTR или LPWSTR. Ваша ServiceMain функция возвращает void и принимает три аргумента типов int, char** и char**.

Измените определение функции ServiceMain, чтобы она была совместима с LPSERVICE_MAIN_FUNCTION.

Приведение ServiceMain к LPSERVICE_MAIN_FUNCTION отключит предупреждение компилятора, но не не решит проблему. Это приведет к тому, что ваша функция будет вызываться , как если бы было объявлено правильно, с непредсказуемыми результатами (неопределенное поведение). Все броски следует рассматривать с подозрением; если ваш компилятор предупреждает вас о несоответствии типов, лучшее решение обычно состоит в том, чтобы изменить ваши объявления, чтобы типы соответствовали, а не заставлять компилятор делать вид, что они в порядке.

(Существует ли typedef, LPSTR или LPWSTR, в зависимости от конфигурации?)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...