Call name of function, rather than pointer of function

314 views Asked by At

The manpage for libffi features an example that, essentially, requires a pointer to the function (in the examples case, puts).

However, what do I do if I only know the name of the function, but don't actually have a pointer (which would usually happen if ffi is used in, say, dynamic programming languages)?

Say, I want to do something like this (pseudocode):

cif = null
s = "Hello World"
args = []
values = []
args[0] = ffi.type_pointer
values[0] = address_of(s)
if(ffi.prepare(cif, ffi.DEFAULT_ABI, ffi.type_uint, args)):
     ffi.call(cif, "puts", values)

In short, i want to have libffi dynamically look up the function (if that's supported by ffi in the first place) similar to dlfcn/LoadLibrary, and then call it with the supplied FFI CIF types.

Is such a thing possible with libffi? What would a simple example look like?

1

There are 1 answers

0
Jonathan Leffler On BEST ANSWER

There are two possibilities - one requiring premeditation on the part of the programmer.

Depending on the o/s, there are facilities associated with shared libraries for finding symbols from the program or its shared libraries.

On many Unix systems and Linux specifically, the facilities are declared in <dlfcn.h> and are dlopen() and dlsym() (and dlclose(), etc). Given an appropriate handle for the shared library, then you can use:

int (*ffi_ptr)(const char *) = dlsym(ffi_handle, "ffi_function_name");

You have to consider the casting - usually brutal - to avoid compilation warnings.

The alternative, premeditated technique is to build a table of function names and function pointers, in which you can search for the name and use the corresponding pointer:

struct ptr_function
{
    void (*func_ptr)(void);
    const char *func_name;
};

static const struct ptr_function[] =
{
    { func_1, "func_1"       },
    { func_2, "func_2"       },
    { func_2, "func_synonym" },
};

enum { NUM_PTR_FUNCTION = sizeof(ptr_function) / sizeof(*ptr_function) } ;

Note that this technique allows for synonyms in a way that the dlsym() mechanism does not. However, the premeditation is often a major stumbling block. It is a technique that harks back to the 80s and early 90s when shared libraries were not universally available. Once again, the need for casts can make the code somewhat more complex.