Сегодня мне нужна была небольшая библиотека для рекурсивного перечисления всех файлов в папке и всех подпапках. Поэтому я решил создать небольшую библиотеку, она очень проста и содержит только две функции:
bool __cdecl isDir(std::string dir);
void __cdecl listDir(std::string dir, std::vector<std::string> &files, bool recursive);
Функция этих тихо говорит сама за себя.
Он содержит один заголовочный файл, который определяет класс FR
и я экспорт что с помощью
__declspec (dllexport)
Причина, по которой я беспокоюсь о создании этой небольшой библиотеки, заключается в том, что она может использоваться в будущих проектах без необходимости постоянно включать исходные файлы в мои проекты.
Вот так я пытаться Для вызова одной из функций:
FR *clazz = new FR();
clazz->isDir("C:/path/to/dir");
И это сгенерированная ошибка:
IntelliSense: функция «FR :: isDir» (объявлена в строке 11 «C: \ dev \ FileRecursionDLL \ inc \ fr.h») недоступна
[Fr.cpp]
#include "fr.h"
using namespace std;
BOOL APIENTRY DllMain(HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
return TRUE;
}
DllExport bool __cdecl FR::isDir(string dir){
struct stat fileInfo;
stat(dir.c_str(), &fileInfo);
if (S_ISDIR(fileInfo.st_mode)){
return true;
}
else{
return false;
}
}
DllExport void __cdecl FR::listDir(string dir, vector<string> &files, bool recursive){
DIR *dp; //create the directory object
struct dirent *entry; //create the entry structure
dp = opendir(dir.c_str()); //open directory by converting the string to const char*
if (dir.at(dir.length() - 1) != '/'){
dir = dir + "/";
}
if (dp != NULL){ //if the directory isn't empty
while (entry = readdir(dp)){ //while there is something in the directory
if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0){ //and if the entry isn't "." or ".."if (isDir(dir + entry->d_name) == true && recursive == true){//check if the new path is a directory, and if it is (and recursion is specified as true), recurse.
files.push_back(string(entry->d_name)); //add entry to the list of files
listDir(dir + entry->d_name, files, true); //recurse
}
else{
files.push_back(string(entry->d_name));//add the entry to the list of files
}
}
}
(void)closedir(dp); //close directory
}
else{
perror("Couldn't open the directory.");
}
}
[Fr.h]
#ifndef FR_H
#define FR_H
#define DllExport __declspec( dllexport )
#include<dirent.h>
#include<vector>
class DllExport FR
{
bool __cdecl isDir(std::string dir);
void __cdecl listDir(std::string dir, std::vector<std::string> &files, bool recursive);
};
#endif
НОТА: Ссылка на библиотеку, которая уже делает это, также будет оценена!
Заранее спасибо!
class
участники private
по умолчанию, struct
участники public
по умолчанию.
Тем не менее, почему бы не сделать общий и простой для создания и использования только заголовочный модуль вместо того, чтобы добавить сложность специфичной для компилятора DLL.
Кроме того, для программирования Windows лучше использовать широкие символьные строки (то есть Unicode).
Пример:
#pragma once
// Copyright (c) 2014 Alf P. Steinbach
#undef UNICODE
#define UNICODE
#include <windows.h>
#include <string> // std::wstring
#include <vector> // std::vector
namespace filesystem{
using std::wstring;
using std::vector;
inline
auto path_join( wstring const& a, wstring const& b )
-> wstring
{
int const len_a = a.length();
int const len_b = b.length();
if( len_a == 0 ) { return b; }
if( len_b == 0 ) { return a; }
wstring result = a;
if( a[len_a - 1] == L'\\' )
{
if( b[0] == L'\\' ) { result.resize( len_a - 1 ); }
}
else if( b[0] != L'\\' )
{
result += L'\\';
}
result += b;
return result;
}enum Recursion { no_recursion, recursive };
inline
auto directory_entries( wstring const& directory_path, Recursion const r = no_recursion )
-> vector<wstring>
{
vector<wstring> result;
WIN32_FIND_DATA state = {};
HANDLE const h = FindFirstFile( path_join( directory_path, L"*.*" ).c_str(), &state );
for(
bool more = (h != INVALID_HANDLE_VALUE);
more;
more = !!FindNextFile( h, &state )
)
{
result.push_back( state.cFileName );
if( r == recursive && !!(state.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
{
// TODO: Check that this isn't a "." or ".." or (hard problem) circular symlink entry.
bool const is_true_subdirectory = false; // <-- Here.
if( is_true_subdirectory )
{
auto const sub_entries = directory_entries(
path_join( directory_path, state.cFileName ), recursive
);
for( auto const& e : sub_entries )
{
result.push_back( e );
}
}
}
}
FindClose( h );
return result;
}
} // namespace filesystem