2015-05-25 3 views
1

Когда это находится в main.cpp, оно работает, но если я положил log.cpp, то получит ошибку LNK2019, когда я вызываю функцию журнала с любым количеством аргументов.C++ Win32 как я могу поместить эти функции в отдельный файл cpp?

string getDate() 
{ 
    SYSTEMTIME localTime; 

    TCHAR strTime[128]; 

    GetLocalTime(&localTime); 

    wsprintf(strTime, "%04d_%02d_%02d_", localTime.wYear, localTime.wMonth, localTime.wDay); 

    stringstream strm; 

    strm << strTime; 

    string date = strm.str(); 

    return &date[0]; 
} 

string getHour() 
{ 
    SYSTEMTIME localTime; 

    TCHAR strTime[128]; 

    GetLocalTime(&localTime); 

    wsprintf(strTime, "%02d:%02d:%02d >> ", localTime.wHour, localTime.wMinute, localTime.wSecond); 

    stringstream strm; 

    strm << strTime; 

    string hour = strm.str(); 

    return &hour[0]; 
} 

void addToStream(stringstream& /*a_stream*/) 
{ 
} 

template<typename T, typename... Args> 
void addToStream(stringstream& a_stream, const T& a_value, Args... a_args) 
{ 
    a_stream << a_value; 
    addToStream(a_stream, a_args...); 
} 

template<typename... Args> 
void log(Args... a_args) 
{ 
    stringstream strm; 
    addToStream(strm, a_args...); 

    string s = strm.str(); 

    HKEY key; 
    char appPath[1024]; 
    DWORD appPathLength = 1024; 

    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\Session Manager\\Environment", 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) 
    { 
     RegCloseKey(key); 
    } 
    else 
    { 
     if (RegQueryValueEx(key, "SERVIDOR_DIR", NULL, NULL, (LPBYTE)&appPath, &appPathLength) != ERROR_FILE_NOT_FOUND) 
     { 
      HANDLE hFile; 

      string dateProv = getDate(); 
      char *date = new char[dateProv.size() + 1]; 
      copy(dateProv.begin(), dateProv.end(), date); 
      date[dateProv.size()] = '\0'; 

      char fileNamePath[MAX_PATH]; 
      strcpy(fileNamePath, appPath); 
      strcat(fileNamePath, "\\logs\\painel\\"); 
      strcat(fileNamePath, date); 
      strcat(fileNamePath, "levaetraz.log"); 
      puts(fileNamePath); 

      hFile = CreateFile(
       fileNamePath,   // file to open 
       GENERIC_WRITE,   // open for writing 
       0,      // share for writing 
       NULL,     // default security 
       // CREATE_NEW,   // existing file only 
       //CREATE_ALWAYS,  // creates a new file, always. 
       OPEN_ALWAYS,   // creates a new file, always. 
       FILE_ATTRIBUTE_NORMAL, // normal file 
       NULL     // no attr. template 
       ); 

      if (hFile != INVALID_HANDLE_VALUE) 
      { 
       // Write to File 
       BOOL bErrorFlag = FALSE; 

       string hourProv = getHour(); 
       char *hour = new char[hourProv.size() + 1]; 
       copy(hourProv.begin(), hourProv.end(), hour); 
       hour[hourProv.size()] = '\0'; 

       char stringLog[1024]; 
       strcpy(stringLog, hour); 
       strcat(stringLog, &s[0]); 
       strcat(stringLog, "\r\n"); 
       puts(stringLog); 

       DWORD dwPtr = SetFilePointer(hFile, 0, NULL, FILE_END); //set pointer position to end file 
       DWORD dwBytesToWrite = lstrlen(stringLog); 
       DWORD a = 0; 

       bErrorFlag = WriteFile(
        hFile,    // open file handle 
        stringLog,   // start of data to write 
        dwBytesToWrite,  // number of bytes to write 
        &dwPtr,    // number of bytes that were written 
        NULL    // no overlapped structure 
        ); 

       delete[] hour; 
      } 

      delete[] date; 

      CloseHandle(hFile); 

      RegCloseKey(key); 
     } 
     RegCloseKey(key); 
    } 
} 

Прежде чем я поставил возможность переменного числа аргументов и журнал вызовов («любая вещь») работает, так как это сработает в log.cpp с переменным числом аргументов?

void log(char *log) 
{ 
    HANDLE hFile; 

    std::string dateProv = getDate(); 
    char *date = new char[dateProv.size() + 1]; 
    std::copy(dateProv.begin(), dateProv.end(), date); 
    date[dateProv.size()] = '\0'; 

    char fileNamePath[MAX_PATH]; 
    strcpy(fileNamePath, "logs/painel/"); 
    strcat(fileNamePath, date); 
    strcat(fileNamePath, "levaetraz.log"); 
    puts(fileNamePath); 

    hFile = CreateFile(
     fileNamePath,   // file to open 
     GENERIC_WRITE,   // open for writing 
     0,      // share for writing 
     NULL,     // default security 
     // CREATE_NEW,   // existing file only 
     //CREATE_ALWAYS,  // creates a new file, always. 
     OPEN_ALWAYS,   // creates a new file, always. 
     FILE_ATTRIBUTE_NORMAL, // normal file 
     NULL     // no attr. template 
     ); 

    if (hFile != INVALID_HANDLE_VALUE) 
    { 
     // Write to File 
     BOOL bErrorFlag = FALSE; 

     std::string hourProv = getHour(); 
     char *hour = new char[hourProv.size() + 1]; 
     std::copy(hourProv.begin(), hourProv.end(), hour); 
     hour[hourProv.size()] = '\0'; 

     char stringLog[1024]; 
     strcpy(stringLog, hour); 
     strcat(stringLog, log); 
     strcat(stringLog, "\r\n"); 
     puts(stringLog); 

     DWORD dwPtr = SetFilePointer(hFile, 0, NULL, FILE_END); //set pointer position to end file 
     DWORD dwBytesToWrite = lstrlen(stringLog); 
     DWORD a = 0; 

     bErrorFlag = WriteFile(
      hFile,    // open file handle 
      stringLog,   // start of data to write 
      dwBytesToWrite,  // number of bytes to write 
      &dwPtr,    // number of bytes that were written 
      NULL    // no overlapped structure 
      ); 

     delete[] hour; 
    } 

    delete[] date; 

    CloseHandle(hFile); 
} 

Я создал log.h и включают в main.cpp

#pragma once 

template<typename... Args> 
void log(Args... a_args); 

Чего не хватает?

+0

Можете ли вы опубликовать полную ошибку компоновщика? – RedAgito

+2

Подождите, журнал затенен шаблоном? Вы должны включить его источники с заголовком – RedAgito

+1

Возможный дубликат [Что такое неопределенная ссылка/неразрешенная ошибка внешнего символа и как ее исправить?] (Http://stackoverflow.com/questions/12573816/what-is-an -unefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – IInspectable

ответ

1

С текущими компиляторами вы не можете скомпилировать код шаблона отдельно, за исключением экземпляров с известными типами/значениями.

Основная проблема, как представляется, этот код:

template<typename T, typename... Args> 
void addToStream(stringstream& a_stream, const T& a_value, Args... a_args) 
{ 
    a_stream << a_value; 
    addToStream(a_stream, a_args...); 
} 

template<typename... Args> 
void log(Args... a_args) 
{ 
    stringstream strm; 
    addToStream(strm, a_args...); 

    string s = strm.str(); 
    // More stuff 

Я предлагаю вам сохранить первый шаблон функции в заголовке вашего, но заменить второй с

template<typename... Args> 
void log(Args... a_args) 
{ 
    stringstream strm; 
    addToStream(strm, a_args...); 
    logString(strm.str()); 
} 

Затем вы можете скомпилировать новый функция logString отдельно, так как это не шаблон.

+0

Правильно! Спасибо! –

Смежные вопросы