Какой предпочтительный способ определения функций для каждой платформы в C ++ - PullRequest
2 голосов
/ 03 апреля 2012

в заголовочном файле я определил следующую функцию

#ifndef OS_H
#define OS_H

#include <string>
#include <vector>

int GetDirectoryFiles(std::string directory, std::vector<std::string> &files);

#endif /* OS_H */

Я хотел бы иметь отдельные реализации для каждой платформы

#include "os.h"
#include <iostream>

#ifdef OSWIN
#include <windows.h>
#elif OSLINUX
#include <dirent.h>
#endif

int GetDirectoryFiles(std::string directory, std::vector<std::string> &files)
#ifdef OSLINUX
{
    DIR *dp;
    struct dirent *dirp;
    if((dp  = opendir(dir.c_str())) == NULL) {
        cout << "Error(" << errno << ") opening " << dir << endl;
        return errno;
    }

    while ((dirp = readdir(dp)) != NULL) {
        files.push_back(string(dirp->d_name));
    }
    closedir(dp);
    return 0;
}
#elif OSWIN
{
    std::clog << "entered!" << std::endl;

    WIN32_FIND_DATA FindFileData;
    HANDLE hFind = FindFirstFile(directory.c_str(), &FindFileData);
    if ( hFind == INVALID_HANDLE_VALUE )
        return -1;

    do {
        files.push_back(FindFileData.cFileName);
    } while(FindNextFile(hFind, &FindFileData) != 0);
    FindClose( hFind );

    return 0;
}
#endif

Есть ли более элегантный способ сделать это (что считается хорошим стилем).

Ответы [ 2 ]

5 голосов
/ 03 апреля 2012

Типичный способ справиться с этим - иметь объявление функции в файле общего заголовка, а затем иметь один файл cpp на платформу, который содержит различные определения этой функции для этой платформы. Тогда ваша система сборки создает и создает ссылки только в соответствующем платформенном файле cpp.

е

Filesystem.h

#include <string>
#include <vector>

int GetDirectoryFiles(std::string directory, std::vector<std::string> &files);

Filesystem_Windows.cpp:

#include "Filesystem.h"

int GetDirectoryFiles(std::string directory, std::vector<std::string> &files);
{
    WIN32_FIND_DATA FindFileData;
    HANDLE hFind = FindFirstFile(directory.c_str(), &FindFileData);
    ...    
    return 0;
}

Filesystem_Linux.cpp:

#include "Filesystem.h"

int GetDirectoryFiles(std::string directory, std::vector<std::string> &files);
{
    DIR *dp;
    struct dirent *dirp;
    ...
    return 0;

}

См. Дерево исходных текстов Qt, очень популярной кроссплатформенной библиотеки C ++, в качестве примера такой структуры.

3 голосов
/ 03 апреля 2012

Я бы использовал #ifdef в тех случаях, когда код почти одинаков для обеих платформ, за исключением нескольких моментов.Например, если у вас есть функция, которая нуждается в clock () / GetTickCount (), но в остальном она та же самая.

Для модулей, которые полностью отличаются (или достаточно отличаются), как в приведенном вами примере, у меня естьподкаталоги в моем каталоге / src, один / src / common для независимой от платформы, а затем один для каждой платформы (/ src / win, / src / linux и т. д.) Я использую одно и то же имя для модуля на каждой платформе,и в make-файле у меня есть условия для определения макроса $ native как / src / win или других в зависимости от того, где я компилирую.Тогда каждое специфичное для платформы имя источника в списке модулей определяется как $ native / [name] .cpp

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