Difference between xxxxx_(), LAPACK_xxxxx() and LAPACKE_xxxxx() functions - c

Let's say I want to use LAPACK to solve a system of linear equations in C (GCC).
I set up the problem as follows:
/* Want to solve Ax=b */
int n = ...; // size
double *A = ...; // nxn matrix
double *b = ...; // length-n vector
int m = 1; // number of columns in b (needs to be in a variable)
double *pivot; // records pivoting
int info; // return value
Now it seems I can use one of three functions to solve this problem.
The first one is this:
dgesv_( &n, &m, A, &n, pivot, b, &n, &info );
I was surprised to see that this did not require any #includes, which seems... weird.
The second function has almost the same signature, except for the prefix LAPACK_ which I think causes less ambiguity and is possibly less error-prone:
#include <lapack/lapacke.h>
LAPACK_dgesv( &n, &m, A, &n, pivot, b, &n, &info );
Note that this requires me to include lapacke.h.
The third function changes the signature somewhat by returning info and not taking all arguments as pointers:
#include <lapack/lapacke.h>
info = LAPACKE_dgesv( LAPACK_COL_MAJOR, n, m, A, n, pivot, b, n);
Again, this function requires lapacke.h. It also requires linking to an extra library with -llapacke.
All three functions need -llapack.
I'm trying to figure out the differences between these functions.
I did some snooping around and I found the following macros in lapacke.h and related header files:
#define LAPACK_GLOBAL(name,NAME) name##_
#define LAPACK_dgesv LAPACK_GLOBAL(dgesv,DGESV)
So it seems that LAPACK_dgesv() and dgesv_() are different names for the exact same function.
However, it appears LAPACKE_dgesv() is something else with possibly a different implementation, especially considering the fact it needs an extra library.
So my question is: what are the differences between these two functions?
The documentation says LAPACKE is a C interface for LAPACK, but then what about the function dgesv_()?
Clearly I can use it normally without needing LAPACKE and without compiling anything in Fortran, so how is that different?
Thanks.
Update
Curiously, the function dgemm_() (matrix multiplication) does not have any LAPACK_dgemm() equivalent.
What's going on?

Notice that LAPACKE_dgesv() features an additional flag which can be LAPACK_COL_MAJOR (usual fortran order) or LAPACK_ROW_MAJOR (usual c order). In case of LAPACK_COL_MAJOR, it just calls LAPACK_dgesv() directly. In case of LAPACK_ROW_MAJOR, LAPACKE_dgesv() will transpose the matrix before calling LAPACK_dgesv(). It is not a new implementation of dgesv_(). Take a look at lapack-3.5.0/lapacke/src/dgesv_work.c In this file, there are minor additional changes about error handling.
LAPACK_dgesv() is defined in the header lapacke.h as LAPACK_GLOBAL(dgesv,DGESV). The macro LAPACK_GLOBAL is defined in lapacke_mangling.h : it just wraps dgesv_ and cares for naming convention if other conventions are used.
So, basically, the function LAPACK_dgesv() just requires the headers of lapacke. Compared to dgesv_, some problems related to naming conventions in libraries may be avoided. But LAPACK_dgesv() is exactly the same as dgesv_(). The function LAPACKE_dgesv() enlarges the scope of LAPACK_dgesv() to handle usual c matrix.But it still calls dgesv_ in the end.
The function dgemm() is part of the BLAS library. A wrapped c version cblas_dgemm() can be found in CBLAS . Again, an additionnal flag CBLAS_ORDER is required, with possible values CblasRowMajor and CblasColMajor.

Related

Why do we need return type and parameter type in funtion declarations? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 days ago.
This post was edited and submitted for review 6 days ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
I've been told we somehow need them so the compiler can continue onwards without having read the definition yet.
Somehow we need them in order for the program to work properly, to avoid conflicts between functions.
Please explain.
If you're going to have separate compilation, meaning that the call versus the definition of a function might be in separate source files, compiled at different times, perhaps months or years apart, you need to decide how information passed to and returned from the function is going to be coordinated.
Let's cover the return value first. Functions can be declared to return int, or double, or char *, or just about any of C's other types. (There are one or two exceptions, types which it's impossible to return, but they needn't concern us here.) But for any given ABI, different values get returned in different ways. Integers and pointers might get returned in a general-purpose processor register. Floating-point values might get returned in a floating-point register. Structures might get returned in some specially-designated memory area. In any case, the called function is going to do the returning, but the calling function (compiled separately) is going to do something with the returned value, so it has to know how to emit the right code to do that. And the only way for it to know (again, under C's separate-compilation model) is the function declaration that indicated the return type. If the calling code thought the function was going to return an int, but the called function actually returned a double, it just wouldn't work, because the called function would place its return value in the spot where return values of type double go, and the calling code would fetch a value from the place where return values of type int go, and it would get indeterminate garbage instead.
Now let's talk about the arguments passed to the function. Again, the mechanisms behind argument passing can take several forms, depending on the type(s) of the argument(s). Again, mismatches are easy, but can cause serious problems. If the programmers writing calling code could be relied on to always pass the correct number of arguments, and of the correct types, we wouldn't need function prototypes — and indeed, that's how C was for the first few years of its life. These days, however, that risk is generally considered as unacceptable, and function prototypes are considered mandatory — by the language standard, by compilers, and by most C programmers. (You might still find a few holdouts, grumbling that prototypes are newfangled or unnecessary, but they're basically an ignorable minority.)
There's a remaining wrinkle concerning "varargs" functions such as printf. Since they don't accept a fixed number of fixed-type arguments, they can't have a prototype that specifies the types of those arguments in advance. An ellipsis ("...") in a function prototype indicates variable arguments that (a) can't be enforced by the compiler but that (b) do have the default argument promotions performed on them, to provide a little more regularity (basically, small types like char and int promoted to int, and float promoted to double). Varargs functions, too, are generally consider old-school and risky if not downright dangerous, and are not recommended for new designs, unless perhaps if they follow the pattern of printf, meaning that the compiler can peek at the format string (if constant) and do the programmer the favor of double-checking the arguments.
The requirements here have been evolving ever since C was invented, and (as discussed in the comments) are still changing. If you have specific questions about what's legal and what's not, what works and what won't, you might want to ask them explicitly, but the answer may depend on which version of C we're talking about.
We can get a good picture of most of the issues just by looking at the standard sqrt function. Suppose you say
double x = sqrt(144);
Once upon a time, that was doubly wrong. Once upon a time, without a function declaration in scope, sqrt would be assumed to return int, meaning that this call wouldn't work, because sqrt actually returns a double. (The compiler would emit code to fetch an int and convert it to the double required by x, but this would be meaningless since there's no int actually returned by sqrt to convert.) But, there's a second problem: sqrt accepts a double argument, which this code doesn't pass, so sqrt wouldn't even receive the correct value to take the square root of.
So, once upon a time, you absolutely needed
extern double sqrt();
(which you probably got from <math.h>) to tell the compiler that sqrt returned a double, and it was your responsibility to call
double x = sqrt(144.);
or
double x = sqrt((double)144);
to cause a double value to be passed.
Today, if you call sqrt out of a clear sky (that is, without a declaration in scope), the compiler is more likely to complain that there's no prototype in scope — that is, it will not quietly assume that sqrt returns int. And if there is a declaration in scope, it will be the prototype declaration
extern double sqrt(double);
which explicitly says that sqrt expects one argument of type double. So, today, the code
double x = sqrt(144);
works fine — the compiler knows to implicitly convert the int value 144 to double before passing it to sqrt.
If you did something really wrong, like calling sqrt(44, 55), in the old days you'd get no complaints (and a very wrong answer), while today you'll get an error saying you've passed too many arguments.
This is probably a longer answer than you were looking for, but in closing, there are two final points to make:
No one would claim that any of this makes perfect sense, or is the way you'd design things from scratch, today. We're living (as ever) with a number of imperfect compromises between modernity and backwards compatibility.
The "guarantees" apparently promised by function prototypes — namely, that automatic argument conversions will be performed if possible, and that compile-time errors will be emitted for gross mismatches — are not absolute, and still depend on a certain amount of programmer care, namely to ensure that the prototypes (upon which everything depends) are actually correct. This generally means putting them in .h files, included both by the caller and the defining source file. See also this question exploring how those vital conventions might be enforced.
Because C Compilers compile code row from top to bottom. If you gonna use any function in your main function you have two ways to do that.
You can code your function first then use main(Compiler code row from top to bottom so it will figure out there is a function)
Like you do you can use parameters to say "Hey there is a function that i made i will use that later" to Compiler.
Example:
Declaration without parameters. COMPILES.
Declaration without parameters and either without type. COMPILES BUT WARNING.
Call BEFORE definition (and no declaration). Compile error. ERROR.
Compiles perfectly (as #Vlad from Moscow pointed, neither parameters are needed in declaration):
1 #include <stdio.h>
2
3 int sum (); // no parameters declaration (if also omit type int, will compile but with warning
4
5 int main (void)
6 {
7 int numa = 2, numb = 3;
8
9 printf ("Sum %d + %d = %d\n", numa, numb, sum ( numa, numb ));
10
11 return 0;
12 }
13
14 int sum ( int numa, int numb )
15 {
16 return numa + numb;
17 }
output:
./ftype_def_dec
Sum 2 + 3 = 5
type int of function ommited (compiled but with warning):
gcc -o ftype_def_dec ftype_def_dec.c
ftype_def_dec.c:3:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
sum ();
^
1 warning generated.
Does not compile (if you omit declaration in a function called in main() BEFORE it's DEFINITION [every detail [types & what/how it does explicited]]):
1 #include <stdio.h>
2
3 // int sum ();
4
5 int main (void)
6 {
7 int numa = 2, numb = 3;
8
9 printf ("Sum %d + %d = %d\n", numa, numb, sum ( numa, numb ));
10
11 return 0;
12 }
13
14 int sum ( int numa, int numb )
15 {
16 return numa + numb;
17 }
gcc -o ftype_def_dec ftype_def_dec.c
ftype_def_dec.c:9:44: error: implicit declaration of function 'sum' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
printf ("Sum %d + %d = %d\n", numa, numb, sum ( numa, numb ));
^
1 error generated.
Because the compiler has to be able to know how your function can be called and used (i.e. what parameters it accepts and what its return type is (although the former can be omitted)) in other calling functions (such as in main).
As mentioned by another answer, the compiler will compile your program from top to bottom. Thus, when it reaches a given line in your program where you use your function, if you had not previously declared it, it would not know how to parse and compile that statement, and/or be able to detect if it consists of an error.
Take a simple example:
void square(int*);
int main(void) {
int number = 4;
number = square(number); // ERROR
// correct usage would be:
square(&number);
return 0;
}
void square(int *num) {
if (!num)
return;
*num *= *num;
}
However, if you had not declared square before main, the compiler would have no way of knowing what do with your call to square inside main, or which of the two calls was an error.
In other words, square is an undeclared identifier if you have not declared the function before calling it.
Just like you cannot do something like:
int main(void) {
int x = 2;
y = x + 5; // ERROR: undeclared identifier 'y'
int y;
return 0;
}
... because the compiler has no idea what y is by the time it reaches its first usage.

passing a constant through a function in C

I have some C function which, among other things, does a modulo operation. So it looks something like
const int M = 641;
void func( ...parameters..) {
int x;
... some operations ...
x %= M;
... some more operations ...
}
Now, what is crucial for me is that the number M here is a constant. If I would not tell the compiler that M is a constant, then I would get much slower performance.
Currently, I am very happy with my function func( .. ) , and I want would like to extend it, so it can work on different moduli. But again, it is crucial here that these moduli are fixed. So I would like to be able to do something like
const int arrayM[] = {641, 31, 75, 81, 123};
and then have for each index in the array of constants array_M[i] a version of the function func, say func_i, which is a copy of the function func, but where array_M[i] replaces the role of M.
In practice, my array of constants arrayM[] will consist of around 600 explicit prime numbers, which I will choose in a particular way so that x % array_M[i] compiles to a very fast modulus function (for instance Mersenne primes).
My question is: How do I do this in C without making 600 copies of my function func, and changing the variable M in the code each time ?
Finally, I would like to ask the same question again for CUDA code. So if I would have a cuda-kernel, where at some point in the code a modulus M operation is carried out, and I want to have different copies of the same kernel (one for each index of array_M).
You may use a define like:
#define F(i,n) void func_##i() { printf("%d\n",n); }
#include <stdio.h>
F(1,641)
F(2,31)
...
int main() {
func_1();
func_2();
}
It is possible to obtain the same effect from a list of constant but it is much much more tricky. See recursive macro.
Most compilers will do constant propagation. You need to turn up the optimisation level high. The only way to be sure however is to examine the assembly code, or to explicitly write the code out with the constants folded in, which is ugly and hard to maintain. C++ allows you to specify a scalar as a template.

How does a forward declaration work?

I understand declaring factorial before main. But how can main calculate the answer when the factorial formula comes after it?
#include <stdio.h>
long long factorial(int);
int main()
{
int n;
long long f;
printf("Enter a number and I will return you its factorial:\n");
scanf_s("%d", &n);
if (n < 0)
printf("No negative numbers allowed!\n"); //prevent negative numbers
else
{
f = factorial(n);
printf("The factorial of %d is %ld\n", n, f);
}
return 0;
}
long long factorial(int n)
{
if (n == 0)
return 1;
else
return (n * factorial(n - 1));
}
But how can main calculate the answer when the factorial formula comes after it?
First thing — main does not calculate the answer; it's your factorial function which does it for you. Also there are 3 steps which I feel you need to know about when writing programs:
You write the code in a file.
You compile the file and the compiler checks for syntactical mistakes, no code calculation is happening in this phase its just mere lexical analysis.
Then linking takes place later. If you receive a linker error, it means that your code compiles fine, but that some function or library that is needed cannot be found. This occurs in what we call the linking stage and will prevent an executable from being generated. Many compilers do both the compiling and this linking stage.
Then when you actually run your code — it's then when the code's control flow goes into the factorial function when the calculation happens, i.e. at runtime. Use a Debugger to see this.
The below image is taken from Compiling, Linking and Building C/C++ Applications
From Wiki:
In computer programming, a forward declaration is a declaration of an
identifier (denoting an entity such as a type, a variable, a constant,
or a function) for which the programmer has not yet given a complete
definition....
This is particularly useful for one-pass compilers and separate
compilation. Forward declaration is used in languages that require
declaration before use; it is necessary for mutual recursion in such
languages, as it is impossible to define such functions (or data
structures) without a forward reference in one definition: one of the
functions (respectively, data structures) must be defined first. It is
also useful to allow flexible code organization, for example if one
wishes to place the main body at the top, and called functions below
it.
So basically the main function does not at all need to know how factorial works.
But how can main calculate the answer when the factorial formula comes after it?
The order in which a C program executes is only partially determined by the order in which the text appears.
For instance, look at the printf function you are using. That doesn't appear in your program at all; it is in a library which is linked to your program.
The forward declaration makes it known (from that point in the translation unit) that there is expected to exist such and such a function having a certain name, arguments and return value.
The simple answer is that your C program is processed from beginning to end before it begins to execute. So by the time main is called, the factorial function has already been seen and processed by the C compiler.
An address is assigned to the compiled factorial function, and that address is "backpatched" into the compiled main function when the program is linked.
The reason forward declarations are needed at all is that C is an old-fashioned language originally designed to allow one-pass compilation. This means that the compiler "translates as it goes": functions earlier in a translation unit are compiled and emitted before later functions are seen. To correctly compile a call to a function which appears later (or, generally, appears elsewhere, like in another translation unit), some information must be announced about that function so that it is known at that point.
It works in this manner: let's take an example to find factorial of 3
Recursion :
As factorial of 0 is 1 and factorial of 1 is also 1, so you can write like
if(n <= 1)
return 1;
Since in main function when compiler sees this f = factorial(n); function, the compiler has no idea of what it means. it doesn't know where the function being defined, but it does know the argument the function is receiving is correct, because it's a user defined function that has its definition after main function.
Hence there should be some way to tell the compiler that I am using a function with name factorial which returns long long with a single int argument; therefore you define a prototype of the function before main().
Whenever you call the function factorial the compiler cross checks with the function prototype and ensures correct function call.
A function prototype is not required if you define the function before main.
Example case where function prototyping is not required :
/*function prototyping is not required*/
long long factorial(int n)
{
//body of factorial
}
int main()
{
...
f=factorial(n);
...
}
Here, the compiler knows the definition of factorial; it knows the return type, the argument type, and the function name as well, before it is called in main.

boost::shared_ptr / QuantLib / stochastic process / path generation

Happy Holidays, everyone !
I'm trying to generate paths of a square root process using the QuantLib/Boost C++ libraries and have encountered what I believe to be an annoying little problem with a fast and simple solution! I'm pretty new to programming so please don't be too harsh on me :)
Here's what I know:
1. The constructor looks like this:
SquareRootProcess( Real b, Real a, Volatility sigma, Real x0 = 0.0,
const boost::shared_ptr<discretization>& d =
boost::shared_ptr<discretization>(new EulerDiscretization))
The crucial function to be used when simulating a stochastic process with QuantLib is
evolve(t,x,dt,dw).
Here's what my code looks like:
#include "stdafx.h"
#include <ql/quantlib.hpp>
#include <ql/stochasticprocess.hpp>
#include <ql/processes/squarerootprocess.hpp>
#include <ql/Processes/eulerdiscretization.hpp>
using namespace QuantLib;
void SquareRootProcessSimulation()
{
Real miu0=0.0;
Real miu;
Real b=0.3;
Real a=5.5;
Volatility sigma=2.02;
BigInteger seed=12324;
MersenneTwisterUniformRng unifMt(seed);
BoxMullerGaussianRng<MersenneTwisterUniformRng> bmGauss(unifMt);
const boost::shared_ptr<StochasticProcess1D::discretization> &d =
boost::shared_ptr<StochasticProcess1D::discretization>(
EndEulerDiscretization);
boost::shared_ptr<SquareRootProcess> squareRootProcess(new
SquareRootProcess(b, a, sigma, miu0, d&));
Time dt=0.1,t=0.0;
Real dw;
Size numVals=10;
for (Size j=1;j<=numVals;++j)
{
dw=bmGauss.next().value;
miu=squareRootProcess->evolve(t,miu0,dt,dw);
std::cout << "Time: " << t+dt << ", miu_t: " << miu << std::endl;
t+=dt;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
SquareRootProcessSimulation();
std::cin.get();
return 0;
}
`
I get no errors when compiling/running the code, but what comes out is a constant value, i.e. something is obviously wrong. I think the problem is in the way I've defined the stochastic process, I cannot quite figure out how the interpret the last part of the constructor with the boost::shared_ptr.
I'm happy to hear any suggestions and hints and thanks for taking the time to read my question!
best regards :)
I'm not quite sure if this will solve the problem, but at least I want to try to help:
First of all let's have a look the constructor
of SquareRootProcess:
SquareRootProcess( Real b,
Real a,
Volatility sigma,
Real x0 = 0.0,
const boost::shared_ptr<discretization>& d = boost::shared_ptr<discretization>(new EulerDiscretization))
As you can see the last two parameters have default values. This means you can call the function like this
SquareRoot(b,a,sigma);
This would mean that the function is called with the values of b, a and sigma. x0 and d ( the last two parameters ) would get their default values as written in the constructor. In this case that would be 0.0 for x0 and a new shared pointer object of the type discretization.
But since you want the value from the last paramter the default value is not the right choice for you.
As far as I can tell the function SquareRootProcess will calculate some stuff and then store the data at the pointers address. Here we come to the second part of the Constructor, the &.
The & in the parameter list means that you pass the function a reference to a shared pointer. This means if you call the function your pointer will ( most likely ) be changed and point to the desired value. If the function has a call by reference you actually don't need to add any signs in the function call. Just to make things clear, the same process with some integers:
void add(int a,int b,int& sum)
{
sum = a + b;
}
int main()
{
int sum;
add(5,12,sum);
// Now sum has the value 17
return 0;
}
So long story short : If a function expects a reference to an object you just pass the object itself in the function call.
So now back to your case:
You just need to create an shared pointer with the type discretization and then pass it on in the function call.
const boost::shared_ptr<StochasticProcess1D::discretization> d(new StochasticProcess1D::discretizitation(/*Whatever constructor is needed for this type*/));
boost::shared_ptr<SquareRootProcess> squareRootProcess(new SquareRootProcess(b, a, sigma, miu0, d));
This should actually do the deal. Just let me know if it worked or if you have any further questions.
Best Regards
As already pointed out, you don't need to pass the discretization object if you don't want to customize it, so
boost::shared_ptr<SquareRootProcess> squareRootProcess(new
SquareRootProcess(b, a, sigma, miu0));
will do for you. The problem I'm seeing is with the repeated calls to evolve; you wrote
miu=squareRootProcess->evolve(t,miu0,dt,dw);
but that will cause each step to always start from miu0. The idea here is that you start from t=0 and x=miu0 and evolve() gives you the new miu at t=0.1. Then you start from t=0.1 and x=miu (not miu0) and generate another step. So you'll have to write something like:
miu = miu0;
for (Size j=1;j<=numVals;++j)
{
...
miu=squareRootProcess->evolve(t,miu,dt,dw); // not miu0
...
}
to get the desired behavior.
As for documentation, you might want to take a look at chapter 6 of Implementing QuantLib, which describes the Monte Carlo framework. It will also get you started with path generators; you can use those to generate paths without having to drive the process yourself.
Oh, by the way: is there any particular reason you're using the docs at sourcearchive.com, instead of the "official" ones on quantlib.org? Is there any way you think we should improve them?

Designing Around a Large Number of Discrete Functions in C

Greetings and salutations,
I am looking for information regrading design patterns for working with a large number of functions in C99.
Background:
I am working on a complete G-Code interpreter for my pet project, a desktop CNC mill. Currently, commands are sent over a serial interface to an AVR microcontroller. These commands are then parsed and executed to make the milling head move. a typical example of a line might look like
N01 F5.0 G90 M48 G1 X1 Y2 Z3
where G90, M48, and G1 are "action" codes and F5.0, X1, Y2, Z3 are parameters (N01 is the optional line number and is ignored). Currently the parsing is coming along swimmingly, but now it is time to make the machine actually move.
For each of the G and M codes, a specific action needs to be taken. This ranges from controlled motion to coolant activation/deactivation, to performing canned cycles. To this end, my current design features a function that uses a switch to select the proper function and return a pointer to that function which can then be used to call the individual code's function at the proper time.
Questions:
1) Is there a better way to resolve an arbitrary code to its respective function than a switch statement? Note that this is being implemented on a microcontroller and memory is EXTREMELY tight (2K total). I have considered a lookup table but, unfortunately, the code distribution is sparse leading to a lot of wasted space. There are ~100 distinct codes and sub-codes.
2) How does one go about function pointers in C when the names (and possibly signatures) may change? If the function signatures are different, is this even possible?
3) Assuming the functions have the same signature (which is where I am leaning), is there a way to typedef a generic type of that signature to be passed around and called from?
My apologies for the scattered questioning. Thank you in advance for your assistance.
1) Perfect hashing may be used to map the keywords to token numbers (opcodes) , which can be used to index a table of function pointers. The number of required arguments can also be put in this table.
2) You don's want overloaded / heterogeneous functions. Optional arguments might be possible.
3) your only choice is to use varargs, IMHO
I'm not an expert on embedded systems, but I have experience with VLSI. So sorry if I'm stating the obvious.
The function-pointer approach is probably the best way. But you'll need to either:
Arrange all your action codes to be consecutive in address.
Implement an action code decoder similar to an opcode decoder in a normal processor.
The first option is probably the better way (simple and small memory footprint). But if you can't control your action codes, you'll need to implement a decoder via another lookup table.
I'm not entirely sure on what you mean by "function signature". Function pointers should just be a number - which the compiler resolves.
EDIT:
Either way, I think two lookup tables (1 for function pointers, and one for decoder) is still going to be much smaller than a large switch statement. For varying parameters, use "dummy" parameters to make them all consistent. I'm not sure what the consequences of force casting everything to void-pointers to structs will be on an embedded processor.
EDIT 2:
Actually, a decoder can't be implementated with just a lookup table if the opcode space is too large. My mistake there. So 1 is really the only viable option.
Is there a better way ... than a switch statement?
Make a list of all valid action codes (a constant in program memory, so it doesn't use any of your scarce RAM), and sequentially compare each one with the received code. Perhaps reserve index "0" to mean "unknown action code".
For example:
// Warning: untested code.
typedef int (*ActionFunctionPointer)( int, int, char * );
struct parse_item{
const char action_letter;
const int action_number; // you might be able to get away with a single byte here, if none of your actions are above 255.
// alas, http://reprap.org/wiki/G-code mentions a "M501" code.
const ActionFunctionPointer action_function_pointer;
};
int m0_handler( int speed, int extrude_rate, char * message ){ // M0: Stop
speed_x = 0; speed_y = 0; speed_z = 0; speed_e = 0;
}
int g4_handler ( int dwell_time, int extrude_rate, char * message ){ // G4: Dwell
delay(dwell_time);
}
const struct parse_item parse_table[] = {
{ '\0', 0, unrecognized_action } // special error-handler
{ 'M', 0, m0_handler }, // M0: Stop
// ...
{ 'G', 4, g4_handler }, // G4: Dwell
{ '\0', 0, unrecognized_action } // special error-handler
}
ActionFunctionPointer get_action_function_pointer( char * buffer ){
char letter = get_letter( buffer );
int action_number = get_number( buffer );
int index = 0;
ActionFunctionPointer f = 0;
do{
index++;
if( (letter == parse_table[index].action_letter ) and
(action_number == parse_table[index].action_number) ){
f = parse_table[index].action_function_pointer;
};
if('\0' == parse_table[index].action_letter ){
index = 0;
f = unrecognized_action;
};
}while(0 == f);
return f;
}
How does one go about function pointers in C when the names (and
possibly signatures) may change? If the function signatures are
different, is this even possible?
It's possible to create a function pointer in C that (at different times) points to functions with more or less parameters (different signatures) using varargs.
Alternatively, you can force all the functions that might possibly be pointed to by that function pointer to all have exactly the same parameters and return value (the same signature) by adding "dummy" parameters to the functions that require fewer parameters than the others.
In my experience, the "dummy parameters" approach seems to be easier to understand and use less memory than the varargs approach.
Is there a way to typedef a generic type of that signature
to be passed around and called from?
Yes.
Pretty much all the code I've ever seen that uses function pointers
also creates a typedef to refer to that particular type of function.
(Except, of course, for Obfuscated contest entries).
See the above example and Wikibooks: C programming: pointers to functions for details.
p.s.:
Is there some reason you are re-inventing the wheel?
Could maybe perhaps one of the following pre-existing G-code interpreters for the AVR work for you, perhaps with a little tweaking?
FiveD,
Sprinter,
Marlin,
Teacup Firmware,
sjfw,
Makerbot,
or
Grbl?
(See http://reprap.org/wiki/Comparison_of_RepRap_Firmwares ).

Resources