I have a pointer to function, assume any signature.
And I have 5 different functions with same signature.
At run time one of them gets assigned to the pointer, and that function is called.
Without inserting any print statement in those functions, how can I come to know the name of function which the pointer currently points to?
You will have to check which of your 5 functions your pointer points to:
if (func_ptr == my_function1) {
puts("func_ptr points to my_function1");
} else if (func_ptr == my_function2) {
puts("func_ptr points to my_function2");
} else if (func_ptr == my_function3) {
puts("func_ptr points to my_function3");
} ...
If this is a common pattern you need, then use a table of structs instead of a function pointer:
typedef void (*my_func)(int);
struct Function {
my_func func;
const char *func_name;
};
#define FUNC_ENTRY(function) {function, #function}
const Function func_table[] = {
FUNC_ENTRY(function1),
FUNC_ENTRY(function2),
FUNC_ENTRY(function3),
FUNC_ENTRY(function4),
FUNC_ENTRY(function5)
}
struct Function *func = &func_table[3]; //instead of func_ptr = function4;
printf("Calling function %s\n", func->func_name);
func ->func(44); //instead of func_ptr(44);
Generally, in C such things are not available to the programmer.
There might be system-specific ways of getting there by using debug symbols etc., but you probably don't want to depend on the presence of these for the program to function normally.
But, you can of course compare the value of the pointer to another value, e.g.
if (ptr_to_function == some_function)
printf("Function pointer now points to some_function!\n");
The function names will not be available at runtime.
C is not a reflective language.
Either maintain a table of function pointers keyed by their name, or supply a mode of calling each function that returns the name.
The debugger could tell you that (i.e. the name of a function, given its address).
The symbol table of an unstripped ELF executable could also help. See nm(1), objdump(1), readelf(1)
Another Linux GNU/libc specific approach could be to use at runtime the dladdr(3) function. Assuming your program is nicely and dynamically linked (e.g. with -rdynamic), it can find the symbol name and the shared object path given some address (of a globally named function).
Of course, if you have only five functions of a given signature, you could compare your address (to the five addresses of them).
Notice that some functions don't have any ((globally visible) names, e.g. static functions.
And some functions could be dlopen-ed and dlsym-ed (e.g. inside plugins). Or their code be synthetized at runtime by some JIT-ing framework (libjit, gccjit, LLVM, asmjit). And the optimizing compiler can (and does!) inline functions, clone them, tail-call them, etc.... so your question might not make any sense in general...
See also backtrace(3) & Ian Taylor's libbacktrace inside GCC.
But in general, your quest is impossible. If you really need such reflective information in a reliable way, manage it yourself (look into Pitrat's CAIA system as an example, or somehow my MELT system), perhaps by generating some code during the build.
To know where a function pointer points is something you'll have to keep track of with your program. Most common is to declare an array of function pointers and use an int variable as index of this array.
That being said, it is nowadays also possible to tell in runtime which function that is currently executed, by using the __func__ identifier:
#include <stdio.h>
typedef const char* func_t (void);
const char* foo (void)
{
// do foo stuff
return __func__;
}
const char* bar (void)
{
// do bar stuff
return __func__;
}
int main (void)
{
func_t* fptr;
fptr = foo;
printf("%s executed\n", fptr());
fptr = bar;
printf("%s executed\n", fptr());
return 0;
}
Output:
foo executed
bar executed
Not at all - the symbolic name of the function disappears after compilation. Unlike a reflective language, C isn't aware of how its syntax elements were named by the programmer; especially, there's no "function lookup" by name after compilation.
You can of course have a "database" (e.g. an array) of function pointers that you can compare your current pointer to.
This is utterly awful and non-portable, but assuming:
You're on Linux or some similar, ELF-based system.
You're using dynamic linking.
The function is in a shared library or you used -rdynamic when linking.
Probably a lot of other assumptions you shouldn't be making...
You can obtain the name of a function by passing its address to the nonstandard dladdr function.
set your linker to output a MAP file.
pause the program
inspect the address contained in the pointer.
look up the address in the MAP file to find out which function is being pointed to.
A pointer to a C function is an address, like any pointer. You can get the value from a debugger. You can cast the pointer to any integer type with enough bits to express it completely, and print it. Any compilation unit that can use the pointer, ie, has the function name in scope, can print the pointer values or compare them to a runtime variable, without touching anything inside the functions themselves.
Related
Why do we need to declare global variables before function defining and declaring since we call this function after this variable declaration? Isn't it that compiler read line by line? I mean while calling the function compiler should know what's x.
void function()
{
x += 3
}
int x = 3;
int main(void)
{
function();
return 0;
}
And one more question. I know that we can define function after main function provided we declared this function before main. Then how does main function see these functions after main function? Does the compiler first read the whole file and then run main() or sth?
You can think at the job of the compiler like this; it reads the source file token by token (not exactly line by line) and when sufficient tokens are read, it outputs the translation. It repeats that, until the source file is (correctly) finished: the job of the compiler is done.
For every token the compiler reads, it needs to know what the token represents. If it doesn't know, an error is generated.
So, while compiling your function
void function()
{
x += 3
}
it encounters an "x" but does not know what it represents (an integer? A float? Something else?). -error-.
Why do we need to declare global variables before function defining and declaring
Declaration and Definition are two different things. The compiler needs a declaration in order to know how to manage an identifier; the real definition can be somewhere else, even in another source (or already compiled) file.
And one more question. I know that we can define function after main function provided we declared this function before main. Then how does main function see these functions after main function? Does the compiler first read the whole file and then run main() or sth?
As explained before, all the compiler needs is a declaration, so it can output correct (object) code. If you declare function(), then define main(), then define function(), the compiler has enough to generate correct output, which will consist of code for main() and code for function() (we can say "in this order"). The next step, the linker, will take care to connect these two functions.
The definition of function() could also be absent: the compiler still would generate correct code for main(); the linker would instead complain, unless you tell it where to find the definition/implementation of function().
Also note that a definition is also a declaration. So if in your source you declare function() and then main(), you don't need forward declaration.
In the comments I've read that perhaps you are confusing interpreters with compilers - this is true, if you try to compare Python with C: very different beasts. A big difference is compiler vs interpreter, the compiler generates data (object code) but does not link it (and neither runs it). An interpreter instead is a compiler+linker+runtime, all packed together. Normally a compiler generates code that is much faster than the equivalent interpreted program, but to do this it needs accurate informations (precise types and declarations) and often (always?) is less versatile. The interpreter is often more versatile but it can not exploit all the optimizazions a good compiler can do.
Why do we need to declare global variables before function defining
and declaring since we call this variablefunction after this
declaration?
The c language is a strictly typed language. When the compiler processes an identifier it needs to determine its type to generate correct object code.
It is not necessary that a global variable used in a function shall be declared exactly before the function definition. But in any case it shall be declared before its usage in a function.
Here is a demonstrative program.
#include <stdio.h>
void function( void )
{
extern int x;
x += 3;
}
int x = 3;
int main( void )
{
function();
printf( "x = %d\n", x );
}
The program output is
x = 6
Here the variable x declared within the function refers to the global variable x defined after the function.
Then how does main function see these functions after main function?
Does the compiler first read the whole file and then run main() or
sth?
C is a compilation language. It does not run programs. It generates object code that then after some processing by the linker can be run.
In the point where a function is used what the compiler is need is the type of the function that to check whether the function is used correctly. If the function is an inline function then it can substitute its call for the function body It can rebuild the object code when the inline definition in the translation unit will be known.
How can I retrieve the function pointer that was used to call a function, from within the function itself? Here's an example of what I need to accomplish:
struct vtable {
void (*func)(void);
};
void foobar(void) {
// How can I get the address of t.func from here?
}
int main(void)
{
struct vtable t = { foobar };
t.func();
return 0;
}
In particular I would like to know if this can be done without using additional parameters in the function definition, ie. not this way:
struct vtable {
void (*func)(struct vtable t);
};
void foobar(struct vtable t) {
...
}
int main(void)
{
struct vtable t = { foobar };
t.func(t);
return 0;
}
This is impossible in portable C. It's also impossible on typical implementations.
When you have a function call
int main(void) {
…foobar(…)…
}
there is no way for foobar to know that it was called by main using C language constructs alone. Many implementations make this information available through debugging features that let you explore the call stack, which the implementation maintains under the hood so as to keep track of where return goes to. In practice this doesn't always match the calling structure in the source code due to compile-time transformations such as inlining.
When the function is determined through a function pointer variable, typical implementations do not keep track of this information at all. A typical way to compile t.func() is:
Load the function pointer t.func into a processor register r.
Push the current instruction pointer to the call stack.
Branch to the address stored in r.
There is no information in memory that links steps 1 and 3. Other things may have happened between steps 1 and 3 depending on how the optimizer handled this particular chunk of code.
If you need to know from which “object” a “method” was called, you need to pass a pointer to the object to the function that is the method. This is how object-oriented languages with actual methods work: under the hood, there is an extra “this” or “self” argument, even if the language doesn't make it explicit.
the problem that I'm trying to solve is how to get the address of the struct without altering the function's list of arguments
The only way to do that, short of doing it the correct way with parameter passing, is to have the caller store the address in a global variable. That's ugly but possible:
#include <stdio.h>
struct vtable {
void (*func)(void);
};
static struct vtable* lastcall;
#define call(x, func) do { lastcall=&(x); (x).func(); } while(0)
void foobar(void) {
printf("foobar caller: %p\n", (void*)lastcall);
}
int main(void)
{
struct vtable t = { foobar };
printf("Address of t: %p\n", &t);
call(t, func);
return 0;
}
I wouldn't recommend the above - it is better if you change the API to include the struct, then hide that part behind a macro if you must.
Discarding everything that's portability, it is of course also possible to dissect the stack and find the caller address there. This is ABI-specific though, and you might have to do it in assembler.
No, it is not possible. How should a function know by which way it is called?
Consider if you call the function without using a structure holding its pointer, like this:
foobar();
You need to invent some way to pass the requested value as a parameter.
I can give you a working answer, but it won't be a pretty one.
C is a pretty chill language when it comes to accessing memory. In fact you can access the entire program stack from any function, this means that you can access main variables from foobar.
Knowing this is as powerfull as it is usually a bad idea.
For your problem, you can search any pointer to your foobar function in a range. Simply by creating a struct vtable pointing to ARBITRARY addresses stored at the stack and then checking if the func field is the same as the address of foobar.
Usually this will yield a SIGSEGV, to avoid this you can limit the addresses used to stack valid addresses using pointer arithmetic.
Here you have a working example in "pure" c (simply play with the RANGE define). But i have to warn you again, dont use this in the real world, unless you want to flex on your hacking skills.
#include <stdio.h>
#define RANGE 100
struct vtable {
void (*func)(void);
};
void foobar(void) {
int a[1]; //We control the stack from this address!
for (int i = 0; i < RANGE; i++) { //We are basically doing a buffer overflow
if (a[i] > a && a[i] < a+RANGE) { //Ignore addresses too far to prevent SEGF
struct vtable *t = (struct vtable*)a[i];
if (t->func == foobar)
printf("[FOOBAR] Address of t is: %x\n", a[i]);
}
}
}
int main(void)
{
struct vtable t = { foobar };
printf("[MAIN] Address of t: %x\n", &t);
t.func();
return 0;
}
Have a nice day!
First of all, you cannot get the address of t if you don't pass any reference to it. This is like trying to follow a pointer back to it's pointer. Pointers in general don't work in the reverse, and this is the reason to write data structures like double linked lists, or similar. Simply you can have millions of such pointers, all pointing to this function, so there's nothing in the function address that allow you to know where the function pointer was stored.
Once said that:
In your first paragraph you say:
How can I retrieve the function pointer that was used to call a function, from within the function itself?
Well, that's preciselly what you get when you use the plain name of the function (as in main) you can then execute that function using a (probably non empty) argument list, as you do in (). You don't know where your function has been called from, but what is true, is that if your program control is inside the body of it, it must have been called from the beginning, so using the function name inside the function could be a way to get a function's pointer. But you cannot get it further and get the structure where that pointer was used... this information is not passed in to your function, you have no means to get to it. This is the same problem as when you are forced to pass an array length to a function because there's nothing in the array that allows you to get how large it is.
I have not checked thoroughly your code, as it is just a snippet of code, that needs some adjustments to evolve into fully executable code, but from my point of view it is correct and will do what you are thinking on. Just test, the computer is not going to break if you make a mistake.
Beware in your code you have passed a full struct record by value, and that will make a full copy of the struct in order to put it in the parameter stack. Probably what you want is something like:
struct vtable {
void (*func)(void); /* correct */
};
void foobar(void) {
// How can I get the address of t.func from here?
/* if you want to get the address of the function, it is
* easy, every function knows its address, is in its
* name */
void (*f)(void) = foobar; /* this pointer is the only one
* that could be used to call
* this function and be now
* executing code here. :) */
/* ... */
f(); /* this will call foobar again, but through the pointer
* f, recursively (the pointer although, is the same) */
}
int main(void)
{
struct vtable t = { foobar };
t.func();
return 0;
}
It is very common to see functions that use callbacks to be executed on behalf of the calling code. Those functions is common also to require pointers to strcutres that represent the context they are called in behalf of. So don't hesitate to pass arguments to your function (try not to pass large structures by value, as you do in your example ---well, I recognize it is not large, it has only a pointer) but anyway, that is very common. OOP implementation rests deeply on these premises.
I previously asked a question about C functions which take an unspecified number of parameters e.g. void foo() { /* code here */ } and which can be called with an unspecified number of arguments of unspecified type.
When I asked whether it is possible for a function like void foo() { /* code here */ } to get the parameters with which it was called e.g. foo(42, "random") somebody said that:
The only you can do is to use the calling conventions and knowledge of the architecture you are running at and get parameters directly from the stack. source
My question is:
If I have this function
void foo()
{
// get the parameters here
};
And I call it: foo("dummy1", "dummy2") is it possible to get the 2 parameters inside the foo function directly from the stack?
If yes, how? Is it possible to have access to the full stack? For example if I call a function recursively, is it possible to have access to each function state somehow?
If not, what's the point with the functions with unspecified number of parameters? Is this a bug in the C programming language? In which cases would anyone want foo("dummy1", "dummy2") to compile and run fine for a function which header is void foo()?
Lots of 'if's:
You stick to one version of a compiler.
One set of compiler options.
Somehow manage to convince your compiler to never pass arguments in registers.
Convince your compiler not to treat two calls f(5, "foo") and f(&i, 3.14) with different arguments to the same function as error. (This used to be a feature of, for example, the early DeSmet C compilers).
Then the activation record of a function is predictable (ie you look at the generated assembly and assume it will always be the same): the return address will be there somewhere and the saved bp (base pointer, if your architecture has one), and the sequence of the arguments will be the same. So how would you know what actual parameters were passed? You will have to encode them (their size, offset), presumably in the first argument, sort of what printf does.
Recursion (ie being in a recursive call makes no difference) each instance has its activation record (did I say you have to convince your compiler never optimise tail calls?), but in C, unlike in Pascal, you don't have a link backwards to the caller's activation record (ie local variables) since there are no nested function declarations. Getting access to the full stack ie all the activation records before the current instance is pretty tedious, error prone and mostly interest to writers of malicious code who would like to manipulate the return address.
So that's a lot of hassle and assumptions for essentially nothing.
Yes you can access passed parameters directly via stack. But no, you can't use old-style function definition to create function with variable number and type of parameters. Following code shows how to access a param via stack pointer. It is totally platform dependent , so i have no clue if it going to work on your machine or not, but you can get the idea
long foo();
int main(void)
{
printf( "%lu",foo(7));
}
long foo(x)
long x;
{
register void* sp asm("rsp");
printf("rsp = %p rsp_ value = %lx\n",sp+8, *((long*)(sp + 8)));
return *((long*)(sp + 8)) + 12;
}
get stack head pointer (rsp register on my machine)
add the offset of passed parameter to rsp => you get pointer to long x on stack
dereference the pointer, add 12 (do whatever you need) and return the value.
The offset is the issue since it depends on compiler, OS, and who knows on what else.
For this example i simple checked checked it in debugger, but if it really important for you i think you can come with some "general" for your machine solution.
If you declare void foo(), then you will get a compilation error for foo("dummy1", "dummy2").
You can declare a function that takes an unspecified number of arguments as follows (for example):
int func(char x,...);
As you can see, at least one argument must be specified. This is so that inside the function, you will be able to access all the arguments that follow the last specified argument.
Suppose you have the following call:
short y = 1000;
int sum = func(1,y,5000,"abc");
Here is how you can implement func and access each of the unspecified arguments:
int func(char x,...)
{
short y = (short)((int*)&x+1)[0]; // y = 1000
int z = (int )((int*)&x+2)[0]; // z = 5000
char* s = (char*)((int*)&x+3)[0]; // s[0...2] = "abc"
return x+y+z+s[0]; // 1+1000+5000+'a' = 6098
}
The problem here, as you can see, is that the type of each argument and the total number of arguments are unknown. So any call to func with an "inappropriate" list of arguments, may (and probably will) result in a runtime exception.
Hence, typically, the first argument is a string (const char*) which indicates the type of each of the following arguments, as well as the total number of arguments. In addition, there are standard macros for extracting the unspecified arguments - va_start and va_end.
For example, here is how you can implement a function similar in behavior to printf:
void log_printf(const char* data,...)
{
static char str[256] = {0};
va_list args;
va_start(args,data);
vsnprintf(str,sizeof(str),data,args);
va_end(args);
fprintf(global_fp,str);
printf(str);
}
P.S.: the example above is not thread-safe, and is only given here as an example...
I'm using the XC8 compiler. For that, you have to define your own void putch(char data) function in order for functions like printf() to work, as is described here. Basically, putch() is the function which is used to write characters to stdout.
I now want to change this function on the fly. I have two different functions, putch_a() and putch_b() and want to be able to change which one is used for putch() itself, on the fly.
I thought of this:
unsigned use_a_not_b;
void putch(char data) {
if (use_a_not_b) {
putch_a(data);
} else {
putch_b(data);
}
}
However, this reduces execution speed. Would there be a way to use pointers for this? I have read this answer, and made the following code:
void putch_a(char data);
void putch_b(char data);
void (*putch)(char) = putch_a; // to switch to putch_a
void (*putch)(char) = putch_b; // to switch to putch_b
Would that work? Is there a faster or better-practice way?
No, and why not
To answer your question: no you can't, in the way that you are thinking (i.e. function pointer). What a function pointer is is a variable with an address of another variable. To illustrate, consider how this works when you have a function pointer foo pointing to function bar.
int bar() {
}
void baz(int (*foo)()) {
int x = foo(); // Calls the function pointed to bar foo
}
int main() {
int (*foo)();
foo = &bar;
baz(foo); // Cal baz() passing it foo, which points to bar()
}
What foo holds is the address of bar. When you pass foo to some function that expects a function pointer parameter (in this case baz()), the function dereferences the pointer, i.e. looks at the memory address associated with foo, gets the address sored in it, in our case the the address of bar, and then calls a function (in our case, bar) at that address. To be very careful about this: in the above example baz() says
Let me look at the memory associated with foo, it has another address in it
Load that address from memory, and call a function at that address. That function returns an int and takes no parameters.
Let's contrast this with a function that calls bar() directly:
void qux() {
int x = bar(); // Call bar()
}
In this case there is no function pointer. What there is, is an address, supplied by the linker. The linker lays out all the functions in your program, and it knows, for instance that bar() is at address 0xDEADBEEF. So in qux() there is just a jump 0xDEADBEEF call. In contrast in baz() there is something like (pseudo-addembly):
pop bar off the stack into register A
read memory address pointed to by register A into register B
jump to memory location pointed to by register B
The way putch() gets called from printf(), for instance, is exactly like qux() calls bar(), and not like the way baz() does: putch gets statically linked into your program, so the address of putch() is hardcoded in there, simple because fprintf() doesn't take a function pointer to call for a parameter.
Why #define is not the answer
#define is a preprocessor directive, that is, "symbols" defined with #define are replaced with their values before the compiler even sees your code. This means that #define makes your program less dynamically modifiable not more. This is desirable in some cases, but in your case it will not help you. To illustrate if you define a symbol like this:
#define Pi 3.14
Then everywhere you use Pi it is as if you typed 3.14. Bacause Pi does not exist, as far as the compiler is concerned, you cannot even take an address of it to make a pointer to it.
Closest you can get to a dynamic putch
Like the others have said, you can have some sort of case statement, conditional, or a global pointer, but the putch function itself has to be there in the same form.
Global function pointer solution:
void (*myPutch)(char);
putch(char ch) {
myPutch(ch);
}
int main() {
myPutch = putch_Type_A();
...
myPutch = putch_Type_B();
}
If/then/else solution has been provided in other answers
goto solution: This would be an ugly (but fun!) hack, and only possible on von Neumann-type machines, but in these conditions you could have your putch look like this:
putch(char ch) {
goto PutchTypeB
PutchTypeA:
// Code goes here
return;
PutchTypeB:
// Code goes here
return;
}
You would then overwrite the goto instruction with goto to some other memory address. You'd have to figure out the opcodes for doing this (from disassembly, probably), and this isn't possible on Harvard architecture machines, so it is out on AVR processors, but it would be fun, if cludgey.
No. That isn't guaranteed to work due to the way code is generated and linked. However...
void (*output_function)(char) = putch_a;
void putch(char c) {
output_function(c);
}
Now you can change output_function whenever you like...
There is no concept of "speed" in C. That's an attribute introduced by implementations. There are fast implementations (or rather, implementations that produce fast code, in the case of "compilers") and slow implementations (or implementations that produce slow code).
Either way, this is unlikely to be a significant bottleneck. Produce a program that solves a useful program, profile it to determine the most significant bottlenecks and work on optimising those.
Before you optimize this, make sure what you have really does reduce execution speed noticeably. In an i/o function there's usually a lot of other stuff going on (checking if buffer space is free, calculating buffer offsets, informing hardware data is available, being interrupted while data is actually transmitted to hardware, etc.) that would make a single extra if/else inconsequential.
In most cases your first block should be fine.
In comments you mention maybe needing to extend this structure to multiple putch() functions.
Maybe try
enum PUTCH { sel_putch_a, sel_putch_b, ... };
enum PUTCH putch_select;
void putch(char c) {
switch(putch_select) {
case sel_putch_a : putch_a(c); break;
case sel_putch_b : putch_b(c); break;
/* ... */
}
}
The compiler should be able to optimize the switch statement to a simple computation and a goto. If the putch_<n> functions are inlineable, this doesn't even cost an extra call/return.
The solution using a pointer-to-function in another answer is more flexible in terms of being able to change the available putch functions on the fly, or define them in other files (for example, if you're writing a library or framework to be used by others), but it does require an extra call/return overhead (compared to the simple case of just defining a single putch function).
I am trying to do something like the following
enum types {None, Bool, Short, Char, Integer, Double, Long, Ptr};
int main(int argc, char ** args) {
enum types params[10] = {0};
void* triangle = dlopen("./foo.so", RTLD_LAZY);
void * fun = dlsym(triangle, ars[1]);
<<pseudo code>>
}
Where pseudo code is something like
fun = {}
for param in params:
if param == None:
fun += void
if param == Bool:
fun += Boolean
if param == Integer:
fun += int
...
returnVal = fun.pop()
funSignature = returnval + " " + funName + "(" + Riffle(fun, ",") + ")"
exec funSignature
Thank you
Actually, you can do nearly all you want. In C language (unlike C++, for example), the functions in shared objects are referenced merely by their names. So, to find--and, what is most important, to call--the proper function, you don't need its full signature. You only need its name! It's both an advantage and disadvantage --but that's the nature of a language you chose.
Let me demonstrate, how it works.
#include <dlfcn.h>
typedef void* (*arbitrary)();
// do not mix this with typedef void* (*arbitrary)(void); !!!
int main()
{
arbitrary my_function;
// Introduce already loaded functions to runtime linker's space
void* handle = dlopen(0,RTLD_NOW|RTLD_GLOBAL);
// Load the function to our pointer, which doesn't know how many arguments there sould be
*(void**)(&my_function) = dlsym(handle,"something");
// Call something via my_function
(void) my_function("I accept a string and an integer!\n",(int)(2*2));
return 0;
}
In fact, you can call any function that way. However, there's one drawback. You actually need to know the return type of your function in compile time. By default, if you omit void* in that typedef, int is assumed as return type--and, yes, it's a correct C code. The thing is that the compiler needs to know the size of the return type to operate the stack properly.
You can workaround it by tricks, for example, by pre-declaring several function types with different sizes of return types in advance and then selecting which one you actually are going to call. But the easier solution is to require functions in your plugin to return void* or int always; the actual result being returned via pointers given as arguments.
What you must ensure is that you always call the function with the exact number and types of arguments it's supposed to accept. Pay closer attention to difference between different integer types (your best option would be to explicitly cast arguments to them).
Several commenters reported that the code above is not guaranteed to work for variadic functions (such as printf).
What dlsym() returns is normally a function pointer - disguised as a void *. (If you ask it for the name of a global variable, it will return you a pointer to that global variable, too.)
You then invoke that function just as you might using any other pointer to function:
int (*fun)(int, char *) = (int (*)(int, char *))dlsym(triangle, "function");
(*fun)(1, "abc"); # Old school - pre-C89 standard, but explicit
fun(1, "abc"); # New school - C89/C99 standard, but implicit
I'm old school; I prefer the explicit notation so that the reader knows that 'fun' is a pointer to a function without needing to see its declaration. With the new school notation, you have to remember to look for a variable 'fun' before trying to find a function called 'fun()'.
Note that you cannot build the function call dynamically as you are doing - or, not in general. To do that requires a lot more work. You have to know ahead of time what the function pointer expects in the way of arguments and what it returns and how to interpret it all.
Systems that manage more dynamic function calls, such as Perl, have special rules about how functions are called and arguments are passed and do not call (arguably cannot call) functions with arbitrary signatures. They can only call functions with signatures that are known about in advance. One mechanism (not used by Perl) is to push the arguments onto a stack, and then call a function that knows how to collect values off the stack. But even if that called function manipulates those values and then calls an arbitrary other function, that called function provides the correct calling sequence for the arbitrary other function.
Reflection in C is hard - very hard. It is not undoable - but it requires infrastructure to support it and discipline to use it, and it can only call functions that support the infrastructure's rules.
The Proper Solution
Assuming you're writing the shared libraries; the best solution I've found to this problem is strictly defining and controlling what functions are dynamically linked by:
Setting all symbols hidden
for example clang -dynamiclib Person.c -fvisibility=hidden -o libPerson.dylib when compiling with clang
Then using __attribute__((visibility("default"))) and extern "C" to selectively unhide and include functions
Profit! You know what the function's signature is. You wrote it!
I found this in Apple's Dynamic Library Design Guidelines. These docs also include other solutions to the problem above was just my favorite.
The Answer to your Question
As stated in previous answers, C and C++ functions with extern "C" in their definition aren't mangled so the function's symbols simply don't include the full function signature. If you're compiling with C++ without extern "C" however functions are mangled so you could demangle them to get the full function's signature (with a tool like demangler.com or a c++ library). See here for more details on what mangling is.
Generally speaking it's best to use the first option if you're trying to import functions with dlopen.