如何在scandir中参数化select函数?

时间:2013-09-13 07:37:00

标签: c++ c parameters scandir

scandir()函数扫描目录dir,调用 每个目录条目上的select()为“int(* filter)(const struct dirent *)” 如何将模式值作为参数传递给过滤器中使用的fnmatch(const char * pattern,const char * string,int flags)函数?

这是我的示例代码

int my_selectgrf(const struct dirent *namelist)
{
   int  r = 0;
   char     my_pattern[] = "*.grf";
   r = fnmatch(my_pattern, namelist->d_name, FNM_PERIOD);

   return (r==0)?1:0;
}
scandir("/pub/data/grf", &namelist, my_selectgrf, alphasort);

我的目标是能够使用my_pattern作为输入参数。

1 个答案:

答案 0 :(得分:5)

简短的回答:你做不到。这是一个非常糟糕的API,直到最近2008年(基于glibc中的糟糕设计)将这样的东西添加到POSIX中是完全可耻的。这种API没有办法参数化或传递上下文应该已经废除了20多年。

据说,有一些解决方法:

方法1:使用全局变量,如果您的代码需要是线程安全的,请确保只有一个线程可以通过锁定一次使用具有给定扫描功能的scandir。这当然序列化用法,如果你真的想要从多个线程调用该函数,这可能是不可接受的。

方法2:使用线程本地存储,GCC __thread关键字(或GCC _Thread_local关键字,GCC遗憾地仍然不接受)或POSIX pthread_setspecific和系列。这很干净,但遗憾的是它可能不正确;如果scandir的实现在内部使用多个线程,则该参数可能无法在某些调用回扫描函数时可用。目前,我不相信有scandir的多线程实现。

现在,更好的解决方案:

Ditch scandir并使用适当的API编写自己的函数来执行相同的操作。不过,它只有几行。