hari
hari

Reputation: 9743

scandir match function arguments

I am using scandir to match certain files from a dir. The match function takes const struct dirent *dp argument.

But I also need to pass another argument with it. When I try to do that, compiles gives me a warning (not error) that my match function is of incompatible pointer type.

Is it not allowed to pass another argument to match function? If it's not, I might have to make that particular variable global which I do not want to do.

code snippet:

/* below I am adding new argument - char *str */
match_function (const struct dirent *dp, char *str) {
}

function() {
count = scandir(PATH, &namelist, match_function, alphasort);
}

warning:

warning: passing argument 3 of 'scandir' from incompatible pointer type

Upvotes: 2

Views: 2838

Answers (4)

mlp
mlp

Reputation: 825

To explicitly answer your question

Is it not allowed to pass another argument to match function?

No. The author of scandir() specified what type of match function it expects; as the user of scandir() you must follow that specification, or write your own scandir()-equivalent that does things the way you want as suggested by R...

Upvotes: 2

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215567

Another approach, which may be preferable to using global variables or thread-specific data, is just to write your own replacement for scandir and have it take an extra void * argument which it would pass to the match function. Considering that scandir is easily implemented in less than 50 lines of code, this is perfectly reasonable.

Here is a possible implementation of scandir:

http://git.etalabs.net/cgi-bin/gitweb.cgi?p=musl;a=blob;f=src/dirent/scandir.c

Upvotes: 2

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215567

The only portable and thread/library-safe way to do what you want is with POSIX thread-specific data.

static pthread_key_t key;
static pthread_once_t init = PTHREAD_ONCE_INIT;
static void initfunc()
{
    int r = pthread_key_create(&key);
    assert(r==0);
}

match_function (const struct dirent *dp)
{
    char *str = pthread_getspecific(key);
    /* ... */
}

function() {
    pthread_once(&init, initfunc);
    pthread_setspecific(key, str);
    count = scandir(PATH, &namelist, match_function, alphasort);
}

If you don't care about thread-safety you can just use a global variable for str and make it a lot easier.

Upvotes: 2

geekosaur
geekosaur

Reputation: 61457

Think about it: how would you pass the additional parameter to it? What you're probably looking for is a closure, which isn't supported by the C standard yet although gcc apparently has the ability to do it via nested functions.

Upvotes: 0

Related Questions