2

これは過去に取り上げられたことがあると思います。謝罪いたします。

エラー LNK2019 が発生する理由を知りたいです。
そして、これを解決するためにどの方向に進むべきか。

Errors are LNK2019:
unresolved external symbol __imp__ReportError referenced in function _wmain
unresolved external symbol __imp__Options referenced in function _wmain

これは、Visual Studio 2010 以降でソリューションをビルドしたときに発生します。
上記のメソッドのヘッダー ファイルの内容は、次のように記述されます。

LIBSPEC DWORD Options (int, LPCTSTR *, LPCTSTR, ...);
LIBSPEC DWORD Options (int, LPCTSTR *, LPCTSTR, ...);

メインコード:

#include "Everything.h"

BOOL TraverseDirectory(LPTSTR, LPTSTR, DWORD, LPBOOL);
DWORD FileType(LPWIN32_FIND_DATA);
BOOL ProcessItem(LPWIN32_FIND_DATA, DWORD, LPBOOL);

int _tmain(int argc, LPTSTR argv[])
{
    BOOL flags[MAX_OPTIONS], ok = TRUE;
    TCHAR searchPattern[MAX_PATH + 1], currPath[MAX_PATH_LONG+1], parentPath[MAX_PATH_LONG+1];
    LPTSTR pSlash, pSearchPattern;
    int i, fileIndex;
    DWORD pathLength;

    fileIndex = Options(argc, argv, _T("Rl"), &flags[0], &flags[1], NULL);


    pathLength = GetCurrentDirectory(MAX_PATH_LONG, currPath); 
    if (pathLength == 0 || pathLength >= MAX_PATH_LONG) { /* pathLength >= MAX_PATH_LONG (32780) should be impossible */
        ReportError(_T("GetCurrentDirectory failed"), 1, TRUE);
    }

    if (argc < fileIndex + 1) 
        ok = TraverseDirectory(currPath, _T("*"), MAX_OPTIONS, flags);
    else for (i = fileIndex; i < argc; i++) {
        if (_tcslen(argv[i]) >= MAX_PATH) {
            ReportError(_T("The command line argument is longer than the maximum this program supports"), 2, FALSE);
        }
        _tcscpy(searchPattern, argv[i]);
        _tcscpy(parentPath, argv[i]);

        pSlash = _tstrrchr(parentPath, _T('\\')); 
        if (pSlash != NULL) {
            *pSlash = _T('\0');
            _tcscat(parentPath, _T("\\"));         
            SetCurrentDirectory(parentPath);
            pSlash = _tstrrchr(searchPattern, _T('\\'));  
            pSearchPattern = pSlash + 1;
        } else {
            _tcscpy(parentPath, _T(".\\"));
            pSearchPattern = searchPattern;
        }
        ok = TraverseDirectory(parentPath, pSearchPattern, MAX_OPTIONS, flags) && ok;
        SetCurrentDirectory(currPath);  
    }

    return ok ? 0 : 1;
}

static BOOL TraverseDirectory(LPTSTR parentPath, LPTSTR searchPattern, DWORD numFlags, LPBOOL flags)
{
    HANDLE searchHandle;
    WIN32_FIND_DATA findData;
    BOOL recursive = flags[0];
    DWORD fType, iPass, lenParentPath;
    TCHAR subdirectoryPath[MAX_PATH + 1];

    /* Open up the directory search handle and get the
        first file name to satisfy the path name.
        Make two passes. The first processes the files
        and the second processes the directories. */

    if ( _tcslen(searchPattern) == 0 ) {
        _tcscat(searchPattern, _T("*"));
    }
    /* Add a backslash, if needed, at the end of the parent path */
    if (parentPath[_tcslen(parentPath)-1] != _T('\\') ) { /* Add a \ to the end of the parent path, unless there already is one */
        _tcscat (parentPath, _T("\\"));
    }


    /* Open up the directory search handle and get the
        first file name to satisfy the path name. Make two passes.
        The first processes the files and the second processes the directories. */

    for (iPass = 1; iPass <= 2; iPass++) {
        searchHandle = FindFirstFile(searchPattern, &findData);
        if (searchHandle == INVALID_HANDLE_VALUE) {
            ReportError(_T("Error opening Search Handle."), 0, TRUE);
            return FALSE;
        }


        do {

            fType = FileType(&findData);
            if (iPass == 1) /* ProcessItem is "print attributes". */
                ProcessItem(&findData, MAX_OPTIONS, flags);

            lenParentPath = (DWORD)_tcslen(parentPath);
            /* Traverse the subdirectory on the second pass. */
            if (fType == TYPE_DIR && iPass == 2 && recursive) {
                _tprintf(_T("\n%s%s:"), parentPath, findData.cFileName);
                SetCurrentDirectory(findData.cFileName);
                if (_tcslen(parentPath) + _tcslen(findData.cFileName) >= MAX_PATH_LONG-1) {
                    ReportError(_T("Path Name is too long"), 10, FALSE);
                }
                _tcscpy(subdirectoryPath, parentPath);
                _tcscat (subdirectoryPath, findData.cFileName); /* The parent path terminates with \ before the _tcscat call */
                TraverseDirectory(subdirectoryPath, _T("*"), numFlags, flags);
                SetCurrentDirectory(_T("..")); /* Restore the current directory */
            }

            /* Get the next file or directory name. */

        } while (FindNextFile(searchHandle, &findData));

        FindClose(searchHandle);
    }
    return TRUE;
}

static DWORD FileType(LPWIN32_FIND_DATA pFileData)
{
    BOOL isDir;
    DWORD fType;
    fType = TYPE_FILE;
    isDir =(pFileData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
    if (isDir)
        if (lstrcmp(pFileData->cFileName, _T(".")) == 0
                || lstrcmp(pFileData->cFileName, _T("..")) == 0)
            fType = TYPE_DOT;
        else fType = TYPE_DIR;
    return fType;
}

static BOOL ProcessItem(LPWIN32_FIND_DATA pFileData, DWORD numFlags, LPBOOL flags)
{
    const TCHAR fileTypeChar[] = {_T(' '), _T('d')};
    DWORD fType = FileType(pFileData);
    BOOL longList = flags[1];
    SYSTEMTIME lastWrite;

    if (fType != TYPE_FILE && fType != TYPE_DIR) return FALSE;

    _tprintf(_T("\n"));
    if (longList) {
        _tprintf(_T("%c"), fileTypeChar[fType - 1]);
        _tprintf(_T("%10d"), pFileData->nFileSizeLow);
        FileTimeToSystemTime(&(pFileData->ftLastWriteTime), &lastWrite);
        _tprintf(_T("   %02d/%02d/%04d %02d:%02d:%02d"),
                lastWrite.wMonth, lastWrite.wDay,
                lastWrite.wYear, lastWrite.wHour,
                lastWrite.wMinute, lastWrite.wSecond);
    }
    _tprintf(_T(" %s"), pFileData->cFileName);
    return TRUE;
}
4

2 に答える 2

2

取得しているエラーはlinkerからのものであり、および関数の定義が見つからないことを示しています(どちらも関数から参照されています)。ReportErrorOptionsmain

これらの関数を含むヘッダー ファイルをインクルードしたと言いますが、そのヘッダーにはこれらの関数の宣言しか含まれていません。彼らのサインのようにね。関数の本体 (実装) はありません。そのための定義が必要です。

作成した関数の定義は、通常、*.cppファイルに配置されています。これらの関数を記述した場合は、関数の定義を含むコード ファイルがプロジェクトに追加されていることを確認してください。

作成していない関数 (つまり、再利用可能なコード ライブラリの一部) については、通常*.lib、関数を呼び出すために必要なものを含むファイルをリンカーに提供します。これらの関数がライブラリからのものである場合は*.lib、リンカーが検索するファイルのリストに、関数に付属のファイルを追加したことを確認してください。Visual Studio でこれを行うには、次の手順に従います。

  1. ソリューション エクスプローラーでプロジェクトを右クリックし、その [プロパティ] を開きます。
  2. 「リンカ」カテゴリを展開し、「入力」ノードを選択します。
  3. 「追加の依存関係」フィールドをクリックし、...ボタンを押します。
  4. *.lib表示されるテキスト ボックスの新しい行にファイルの名前を入力します。
于 2013-08-04T16:49:25.233 に答える
1

ヘッダー ファイルで関数を宣言したからといって、その関数の本体がどこかにあるとは限りません。

リンクエラーは、関数に本体がないことを示しています。

.libこれは、適切なライブラリ (ファイル)にリンクしていないことが原因である可能性があります。

于 2013-08-04T16:47:51.583 に答える