今天我需要一个小型库来递归列出文件夹和所有子文件夹中的所有文件。所以我决定创建一个小型库,它非常简单,只包含两个函数:
bool __cdecl isDir(std::string dir);
void __cdecl listDir(std::string dir, std::vector<std::string> &files, bool recursive);
这些功能是安静的自我解释。
它包含一个头文件,用于定义使用
的类FR
和export
__ declspec(dllexport)
我打扰这个小型库的原因是它可以在以后的项目中使用,而无需一直将源文件合并到我的项目中。
这就是我尝试调用其中一个函数的方法:
FR *clazz = new FR();
clazz->isDir("C:/path/to/dir");
这是产生的错误:
IntelliSense:函数“FR :: isDir”(在“C:\ dev \ FileRecursionDLL \ inc \ fr.h”的第11行声明)无法访问
[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
注意:对已经执行此操作的库的引用也将不胜感激!
提前致谢!
答案 0 :(得分:1)
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