Search code examples
clibrariesdlopendlsym

dlopen for different libraries? C


Hi I am working on a program that works like this:

./Filters File [filters...]

The filters can be a lot of .so libraries that I want to create myself and aply them to the File. But all of the libraries have the same function process(a1,a2,a3), it's just that each of them do something different.

I'm trying to use it like this:

/*Open the library*/
if (!(descriptor_lib=dlopen(dir_filter, RTLD_LAZY))) {
    fprintf(stderr, MYNAME": %s\n", dlerror());
    return(1);
}

/*We find the function we want to use*/
if (!(fn=dlsym(descriptor_bib, "process"))) {
    fprintf(stderr, MYNAME": %s\n", dlerror());
    return(1);
}

/*And then I try to use the function*/
printf("Number of chars readed: %d", fn(a1, a2, a3));

But I get this error when I try to compile: error: too many arguments to function ‘fn’

dir_filter is the direction of the library, but its a variable, cause I make a loop to read all the filters, copy in dir_filter the actual one, and then use the code above.

And I think that if I specify the dir_filter with the name of the library, it will work, but I can't do that cause I need to make it work for different filters (different libraries), it will not be always the same. Now i only have 3 libraries but if in a future i wat to expand it i don't want to extend the code everytime I add a new library.

So what I'm doing wrong, or it's imposible to work with dlopen with a variable?

EDIT: The function process is something like this:

int process(char*buff_in, char*buff_out, int tam)

EDIT2: With typedef i could fix the function pointer, that was the problem. Thanks for the replies and sorry for my english.


Solution

  • Assuming that your process function is declared (in your plugin code) as

    int process(int, int, int);
    

    Then, you'll better define a typedef for its signature (within the main program doing the dlsym):

    typedef int process_sig_t (int, int, int); 
    

    And you'll use that to declare the function pointer (there are some "direct" ways to declare in C a function pointer without using a typedef for its signature, but I find them less readable).

    process_sig_t *fnptr = NULL;
    

    The compiler would then know the signature of the function referenced by that pointer.

    (the initialization of fnptr to NULL could be omitted; it makes the code more readable and less error prone, since with a more reproducible behavior)

    which you would fill using dlsym e.g.

    if (!(fnptr=dlsym(descriptor_bib, "process"))) {
      fprintf(stderr, MYNAME": %s\n", dlerror());
      return(1);
    }
    

    The use it

    printf("Number of chars read: %d\n", (*fnptr) (a1, a2, a3));
    

    BTW, function pointers could be called directly:

    // less readable code, we don't know that fnptr is a function pointer
    printf("Number of chars read: %d\n", fnptr (a1, a2, a3));
    

    (it is better to end most printf format strings with \n; otherwise call fflush(3) since stdout is often line-buffered)

    BTW, your question is mostly about understanding function pointers (it would be relevant if the function pointer was obtained thru something else than dlsym, e.g. using some JIT compiling library like GCCJIT).