Conditional substitution of union member in C - c

I have
typedef union
{
void (*fp1p)(void);
void (*fp2p)(uint32_t);
void (*fp3p)(uint32_t, uint32_t);
void (*fp4p)(uint32_t, uint32_t, uint32_t);
uint32_t (*fp5p)(uint32_t);
uint32_t (*fp6p)(uint32_t, uint32_t);
uint32_t (*fp7p)(uint32_t, uint32_t, uint32_t);
} fp;
struct command
{
char *name; //command name
uint32_t minargs;
uint32_t maxargs;
int minval;
int maxval;
fp read_func_pointer;
fp write_func_pointer;
};
struct command commands[] =
{
[0] = { "reg1001", 0,0,0,0, .read_func_pointer.fp6p = TDC1000_SPIByteReadReg, .write_func_pointer.fp4p = TDC1000_SPIByteWriteReg },
//
//
};
And then
if(condition)
{
uint32_t ret_val = commands[0].read_func_pointer.fp6p(…);
}
else
{
commands[0]. write_func_pointer.fp6p(…);
}
How can I make it generic instead of .fp6p?

I don't know if thats an option for you, but how about adding an enum representing the function pointer type to your struct?
In the conditon statement you could switch on the enum and then call the right function pointer.

I think you may use anonymous members for unions:
struct command
{
char *name; //command name
...
union
{
....
void (*fp4p)(uint32_t, uint32_t, uint32_t);
uint32_t (*fp6p)(uint32_t, uint32_t);
};
...
};
You have to change fp6p, etc. names to fp6pw for write_func members. Then call directly commands[0].fp6p(...). Not sure but initialization must be "generic" as you want.

I'd like to clarify.
Suppose we have several commands
struct command commands[] = {
[0] = { "reg1001", 0,0,0,0, .read_func_pointer.fp6p = TDC1000_SPIByteReadReg, .write_func_pointer.fp4p = TDC1000_SPIByteWriteReg },
[1] = = { "reg7201", 0,0,0,0, .read_func_pointer.fp3p = TDC7200_SPIByteReadReg, .write_func_pointer.fp5p = TDC7200_SPIByteWriteReg },
};
I have a generic function to choose an incoming command
For (i=0; I < sizeof(commands); i++)
{
if (strcmp(commands[i].name,args[0])==0)
{
commands[i]. read_func_pointer.<- Here – how can I know what pointer to place?
}
}

Calling a function of signature known only at runtime is not achievable in portable standard C99 or C11; the signature should be known at compile time (and you could extend your code, conceptually by having a tagged union of function pointers, that is by keeping a tag describing the signature). This is so because the calling conventions can (and do) vary with the function signature (the ABI would use different registers for passing different kinds or types of arguments or results).
Alternatively, consider using libffi; it contains some magic (assembler code, dependent of the ABI), which invokes an arbitrary function pointer whose signature is described by some meta-data.
If you are targetting POSIX, you could use some dlopen & dlsym tricks (you might also consider plugin support in frameworks like Qt5 or POCO or Glib...). You might generate (at runtime) some appropriate (glue) C code in generated-code-001.c, compile it by forking some compiler command (e.g. gcc -Wall -O -fPIC generated-code-001.c -shared -o generated-code-001.so), then dlopen that ./generated-code-001.so shared object (on Linux; on MacOSX the compilation command and the file extension are different), and use dlsym to get the function pointer. I am extensively using such tricks in MELT

Related

How to use shared object libraries for enabling/disabling features?

Language: C
Operating System: Red Hat EL
Starting with a "for instance":
Assume I have two libraries: libJUMP.so and libSIT.so.
JUMP contains the function jump() and similarly SIT contains the function sit()
I have an application that I want to provide to different people; they can either get the jump() feature, the sit() feature, or both. However, I would like to NOT use #ifdef if at all possible.
Header for libJUMP.so:
#ifndef JUMP_H_
#define JUMP_H_
#define JUMP_ENABLED
void jump();
#endif /* JUMP_H_ */
Header for libSIT.so:
#ifndef SIT_H_
#define SIT_H_
#define SIT_ENABLED
void sit();
#endif /* SIT_H_ */
I have an application:
#include "jump.h"
#include "sit.h"
int main()
{
// #ifdef JUMP_ENABLED
jump();
// #endif /* JUMP_ENABLED */
// #ifdef SIT_ENABLED
sit();
// #endif /* SIT_ENABLED */
}
So:
Is there a way to do this without using #ifdef? Is there a better way at all?
I have heard we could do this by compiling with both SO libraries, and if one is missing when I run the application on the target system, it could just exclude the feature automatically (using some combination of dlopen() and dlsym()?) Any easy examples, if this is indeed correct? An example with my code from above, if possible :D?
If this is a stupid question, or just not possible, please feel free to tell me so. If there is a similar question that this would be considered a duplicate of, let me know and I will delete this post.
Consider these three files. First, jump.c:
#include <stdio.h>
int jump(const double height)
{
fflush(stdout);
fprintf(stderr, "Jumping %.3g meters.\n", height);
fflush(stderr);
return 0;
}
Second, sit.c:
#include <stdio.h>
int sit(void)
{
fflush(stdout);
fprintf(stderr, "Sitting down.\n");
fflush(stderr);
return 0;
}
Third, example.c to use one or both of the above, depending on whether they (as libjump.so or libsit.so, respectively) exist in the current working directory:
#include <stdio.h>
#include <dlfcn.h>
static const char *jump_lib_path = "./libjump.so";
static int (*jump)(const double) = NULL;
static const char *sit_lib_path = "./libsit.so";
static int (*sit)(void) = NULL;
static void load_dynamic_libraries(void)
{
void *handle;
handle = dlopen(jump_lib_path, RTLD_NOW | RTLD_LOCAL);
if (handle) {
jump = dlsym(handle, "jump");
/* If no jump symbol, we don't need the library at all. */
if (!jump)
dlclose(handle);
}
handle = dlopen(sit_lib_path, RTLD_NOW | RTLD_LOCAL);
if (handle) {
sit = dlsym(handle, "sit");
/* If no sit symbol, the library is useless. */
if (!sit)
dlclose(handle);
}
}
int main(void)
{
int retval;
load_dynamic_libraries();
if (jump) {
printf("Calling 'jump(2.0)':\n");
retval = jump(2.0);
printf("Returned %d.\n\n", retval);
} else
printf("'jump()' is not available.\n\n");
if (sit) {
printf("Calling 'sit()':\n");
retval = sit();
printf("Returned %d.\n\n", retval);
} else
printf("'sit()' is not available.\n\n");
return 0;
}
Let's first compile and run the example program:
gcc -Wall -O2 example.c -ldl -o example
./example
The program outputs that neither jump() or sit() are available. Let's compile jump.c into a dynamic library, libjump.so, and then run the example again:
gcc -Wall -O2 -fPIC -shared jump.c -Wl,-soname,libjump.so -o libjump.so
./example
Now, the jump() function works. Let's compile sit.c, too, and run the example a final time:
gcc -Wall -O2 -fPIC -shared jump.c -Wl,-soname,libsit.so -o libsit.so
./example
Here, both functions get called, and everything just works.
In example.c, jump and sit are function pointers. We initialize them to NULL, so that we can use if (jump) to check if jump points to a valid function.
The load_dynamic_libraries() function uses dlopen() and dlsym() to obtain the function pointers. Note that if the dynamic library is opened successfully, and the necessary symbol is found, we do not dlclose() it because we want to keep the dynamic library in memory. (We only dlclose() it if it looks like it is not the kind of library we want.)
If you want to avoid the if (jump) and if (sit) clauses, you can use stubs like
int unsupported_jump(const double height)
{
return ENOTSUP;
}
int unsupported_sit(void)
{
return ENOTSUP;
}
and at the end of load_dynamic_libraries(), divert the functions to the stubs instead of NULL pointers, i.e.
if (!jump)
jump = unsupported_jump;
if (!sit)
sit = unsupported_sit;
Note that function-like interfaces are easiest to use, because the function pointer acts as the effective prototype. If you need objects, I recommend using getter functions. Objects do work just fine, as long as you remember that dlsym() returns a pointer to the object; using a getter function, that is explicit in the getter function pointer type.
Plug-in interfaces commonly have a single function (say, int properties(struct plugin *const props, const int version)), which is used to populate a structure of function and object pointers. The application supplies the version of the structure it uses, and the plug-in function returns either success or failure, depending on whether it can populate the structure to accommodate that version.
As plug-ins are typically stored in a single directory (/usr/lib/yourapp/plugins/ is very common), you can trivially load all plugins by using opendir() and readdir() to scan the file names in the plug-in directory one by one, dlopen()ing each one, obtaining the properties() function pointer, and calling it to see what kinds of services the plugin provides; typically creating an array or a linked list of the plugin structures.
All of this is very, very simple and straightforward in Linux, as you can see. If you want a specific plug-in functionality example, I recommend you pose that as a separate question, with more details on what kind of functionality the interface should expose -- the exact data structures and function prototypes do depend very much on what kind of application we have at hand.
Questions? Comments?

Optimizing away unused function pointers

I want gcc to optimize away unused function pointers. Ie remove the code completely from the final executable. So far I was not able to achieve this.
Here is updated code:
#include <stdio.h>
struct inner {
void (*fun)(void);
void (*fun2)(void);
};
struct inner2 {
void (*fun)(void);
};
struct foo {
struct inner in;
struct inner2 in2;
};
void lessfun(){
printf("lessfun\n");
}
void morefun(){
printf("morefun\n");
}
const struct foo inst = {
{ .fun = lessfun, .fun2 = morefun },
{ .fun = lessfun }
};
void test(struct foo *f){
f->in.fun();
}
int main(int argc, char *argv){
struct inner2 in = inst.in2;
inst.in.fun();
inst.in.fun2();
in.fun();
/////////////// alt1: nm out | grep morefun -> found
test(&inst);
///////////////
/////////////// alt2: nm out | grep morefun -> not found
struct inner in;
struct inner in2 = inst.in;
in = in2;
test(&in);
///////////////
}
compiler flags: -Os -fdata-sections -Wl,--relax,--gc-sections -ffunction-sections
link flags: -flto -Os -fdata-sections -Wl,--relax,--gc-sections
Compiler: arm-none-eabi-gcc
Here the compiler will include both method1 and method2 into the final program even if they are never used. It is the assignment that seems to make this happen. But if they are never called, it would be nice to completely remove the code to method1 and method2. This obviously happens because technically the function is in fact referenced in the assignment, but since the variable in the assignment is never user it should still be possible to determine that the method is never called.
Do I need to declare it const somehow? How?
How can I have gcc remove the unused functions?
EDIT: I was able to sort of make it work as you see above. But it only works if I do not make a copy of any members of the struct. If a direct copy is made and passed to a function, the compiler fails to optimize unused functions. I'm now 60% certain that this is some kind of optimizer bug.
EDIT2: you may not even reproduce the bug. But here is the scenario that creates it.
struct mydev dev;
struct dev_spi spi;
struct dev_spi sp2 = board.spi0;
sp2.writereadbyte(0);
spi = sp2;
//test(&cpu.spi0);
// using only this call results in correct optimization
// many unused methods pointed to by members of "board" var are gone.
mydev_init(&dev, &spi);
// using this version breaks optimization
// all methods referenced by "board" struct are included in final program
mydev_init(&dev, &sp2);
// this one breaks optimization as well
// same as above.
mydev_init(&dev, &board.spi0);
// there is no difference other than one passes variable directly to the init function
// and the other uses a temp variable.

Clang splits function arguments

If you compile the following with "clang -S -emit-llvm struct.c"
struct _mystruct {
long long int a;
long long int b;
};
struct _mystruct foo(struct _mystruct s) {
s.a += 1;
return s;
}
int main(void) {
struct _mystruct s;
s.a = 8;
s.b = 9;
s = foo(s);
return s.a;
}
... you get (among other things):
define { i64, i64 } #foo(i64 %s.coerce0, i64 %s.coerce1) #0 {
Why does clang split the argument to foo in two? Is there any way I can prevent it from doing that? I want to be able to call it from other LLVM generated code that expects only one argument to foo.
Since LLVM has no way to represent it, Clang encodes the platform ABI this way. In this particular example, it's struct passing by-value which is extremely ABI specific. You will notice this if you provide different target triple to clang - you'll notice that the emitted code is different. I assume from the question this is run on a x64 machine where structs can be passed in registers.

How can I cast an char array to a function pointer in C?

Is it possible to assign with cast to a function pointer a string or char array and then run it?
I have defined a few functions int f1();, int f2();, and so on
In the main() function I have read a string fct_name and declared a pointer to function int (*pv)();
I need to do something like this:
the fct_name can have values "f1" , "f2" and so on..
pv = (some sort of cast)fct_name;
pv();
My point is I want to avoid conditional instructions in favor of direct assignment (because I have a large number of functions in my program)
The code must obviously run.
Assuming you don't have an external library and are trying to call functions declared in your executable, you can do a lookup yourself
#define REGISTER_FUNC(name) {#name, name}
struct funclist
{
const char* name;
void (*fp)(void); //or some other signature
};
struct funclist AllFuncs[] = {
REGISTER_FUNC(f1),
REGISTER_FUNC(f2),
REGISTER_FUNC(f3),
{NULL,NULL} //LAST ITEM SENTINEL
};
Now you can lookup your variable fct_name in AllFuncs. You can use a linear search if the number is small, or insert them all into a hash table for O(1) lookup.
Alternately, if your names really are f1, f2, etc. you can just do
void (*FuncList)(void)[] = {NULL, f1,f2,f3};
...
int idx = atol(fct_name+1);
if (idx && idx < MAX_FUNCS)
FuncList[idx]();
A variant of Carey's answer, in case you're on a *nix system. dlopen() opens up your library. RTLD_LAZY tells the loader to not bother resolving all the library's symbols right away, and to wait for you to try to access them. dlsym() looks up the symbol in question.
Edit: Updated the snippet to better fit your clarification:
#include <dlfcn.h>
int main(int argc, char *argv[])
{
void *handle = dlopen("libexample.so", RTLD_LAZY);
if (handle == NULL) {
// error
}
char fct_name[64];
// read input from terminal here
void *func = dlsym(handle, fct_name);
if (func != NULL) {
// call function here; need to cast as appropriate type
}
}
libexample.so would be a library with your functions, compiled as a shared library, like so:
gcc -Wall -o libexample.so example.c -shared -fPIC
That being said, if you're going to the trouble of compiling a shared library like this, you'll probably just want to call the functions in your binary. You can do that if you link your library in at compile-time:
gcc -Wall -o test test.c -L. -lexample
-L. tells the linker to look for libraries in the current directory (.) and -lexample tells it to link with a library named "libexample.so". If you do this, you can just call the library functions directly within your program.
You can't cast a char array to a function just because the array happens to contain the name of a function. What you need to do is put your function(s) in a DLL and then do this:
HMODULE dll = LoadLibrary("foo.dll");
pv func = (pv)GetProcAddress(module, fct_name);

Example code to trigger Clang's static analyser

I would like to see a small but complete snippet of code that will cause Clang's static analyser to complain. My motivation is mostly that I'm trying to get it to work on my PIC32 code, and I need a way to distinguish between "all the code is fine" and "it's not actually doing anything". It's also partly curiosity, since I can't seem to come up with a simple example myself.
C89/ANSI or C99 is fine, and ideally I'd like to see it pick up a simple memory leak. My usage is
clang --analyze test.c
I found a "bug" in my code (the only one ;-) that triggers by that, and that is not detected by -Wall. I cooked it down to the following
struct elem {
struct elem *prev;
struct elem *next;
};
#define ELEM_INITIALIZER(NAME) { .prev = &(NAME), .next = &(NAME), }
struct head {
struct elem header;
};
#define HEAD_INITIALIZER(NAME) { .header = ELEM_INITIALIZER(NAME.header) }
int main(int argc, char ** argv) {
struct head myhead = HEAD_INITIALIZER(myhead);
}
This is a relatively straight forward implementation of a linked list, but this is not important here. The variable myhead is unused in a common sense application of the term, but for the compiler it is used since inside the initializer the address of a field is taken.
clang correctly analyzes this as
/tmp 11:58 <722>% clang --analyze test-clang.c
test-clang.c:25:15: warning: Value stored to 'myhead' during its initialization is never read
struct head myhead = HEAD_INITIALIZER(myhead);
^ ~~~~~~~~~~~~~~~~~~~~~~~~
1 diagnostic generated.
Edit: I found another one that also detects stack memory proliferation
char const* myBuggyFunction(void) {
return (char[len + 1]){ 0 };
}
This is not detected by gcc, open64 or clang with -Wall, but by clang with --analyze.

Resources