PostgreSQL module - How to map an array of parameters into the function? - c

Am trying to convert a little bit of C test code into a PostgreSQL v1 module
Code originally designed as a simple command line, which takes a variable number - an array - of text arguments; from 3 to 7
the original code's declarations are commented; I'm now trying to convert that into a PG shared object function. All of the arguments to the function will be text strings (base command, options, etc.)
how can I declare/pass the array into the function?
PG_FUNCTION_INFO_V1(embed_0);
Datum
embed_0(PG_FUNCTION_ARGS)
// THIS was the declaration when it was a C executable:
// int main(int argc, char *argv[])
{
// don't think mapping argc to a PG type is needed here, right?
// (argc is not a parameter?)
int *argc; // = PG_GETARG_INT32(0);
char argv[] = PG_GETARG_TEXT_P(0);
int i;
Object *pName, *pCall, *pPart1, *pPart2, *pArgs, *pValue;

If you have a variable number of arguments you need to either:
Declare it VARIADIC;
Create n different signatures for the function with different numbers of arguments; or
In C create only the most general form, the 7-argument variety, and then create SQL function wrappers for the fewer-arguments cases that call the most general form.
If you really only need 3,4,5,6, and 7-argument versions I'd do something like:
CREATE FUNCTION embed0(text,text,text,text,text,text,text) RETURNS text
LANGUAGE 'C' AS 'embed0','embed0';
CREATE OR REPLACE FUNCTION embed0(text,text,text) RETURNS text AS $$
SELECT embed0($1,$2,$2,NULL,NULL,NULL,NULL);
$$ LANGUAGE 'SQL';
// ... etc
If 7 args was just an arbitrary upper bound and you can actually take any number of arguments you should instead just write:
CREATE FUNCTION embed0(text,text,text,VARIADIC text) RETURNS text
LANGUAGE 'C' AS 'embed0','embed0';
and handle the variable arguments in your C function. See the PostgreSQL source code for the concat function for how. Its implementation is text_concat in src/backend/utils/adt/varlena.c on line 3842 in current git head; your line number will differ. Most of the work is done in concat_internal.
Another example is the format function, with C implementation text_format (via lookup in pg_proc.h), located in varlena.c (according to git grep '^text_format'; Pg coding style rules specify that the function name must begin on the hard left of the line), line 3953 in current git. While a more complicated function it might be better as an example for you because it does all the work in one place rather than splitting out for a helper function call. It's declared in pg_proc.h but if it were declared in SQL it'd look something like:
CREATE FUNCTION format(text, VARIADIC text) RETURNS text AS 'internal','text_format';
There you'll see that VARIADIC arguments are accessed like any other from C, using the PG_GETARG_...(argno) macros. The PG_NARGS() macro reports the number of arguments passed. VARIADIC arguments may be null so you have to use PG_ARGISNULL(argno) and handle the case of a null argument.
So: I'd write it as a VARIADIC function using PG_NARGS, PG_GETARG_TEXT_P, PG_ARGISNULL. Because Pg's VARIADIC functions cannot be called implicitly with zero variadic arguments, I'd write a wrapper for the 3-argument case that does:
CREATE OR REPLACE FUNCTION embed_0(text,text,text) RETURNS text AS $$
SELECT embed_0($1,$2,$2, VARIADIC ARRAY[]::text[]);
$$ LANGUAGE 'SQL';
, passing an empty array as the variadic parameter. That way you can call it with 3 args too.
BTW, when coding be aware that the string in a Pg text is not null terminated, unlike those passed to main(). You must use the lengths PostgreSQL provides.. See src/include/fmgr.h, the tutorial, and the text handling in the functions in the source code. Don't use strlen, strcat, strcpy, etc because they expect null-terminated strings.

Related

Can you have in C variable length arguments functions with cases when you don't want to pass any variable?

I want to create a function in C with variable length arguments in which I may not want to pass any variable at some point. I such a thing possible in C? I would like some code snippets if possible. Also, I have to mention that the function will have passed only char* variables when there are passed some variables.
A function with variable arguments must have at least one names argument in order to read the others.
For your particular case, since you want to pass a list of char * arguments you can use NULL to denote the end of the argument list. So in the case where there is nothing to pass, you just pass a singe NULL argument.
This is not supported by standard C.
For a function parameter type list terminated with an ellipsis, there must be at least one named parameter.
For a function defined with an identifier list, the number of arguments in the call must match the number of parameters in the definition; varying numbers of arguments are not supported.
If you will call a function with a varying number of char * arguments, and that number may be zero, you could declare the function with a dummy first argument that is always passed but never used, as with:
void foo(int dummy,...);
Note that passing no arguments is a troublesome design. Normally, routines that accept varying numbers of arguments infer the number of arguments from one or more arguments. For example, the first argument might contain the number of remaining arguments, or it might be a format string (as with printf) from which the number and types of remaining arguments can be deduced. If you want a function to accept zero arguments in some situations, it has to have a way of knowing whether it was called with zero arguments or more. That would require information in some global state, which is typically a bad design.
no you cant
you need at least one known argument
void foo(int dummy, ...)
{
va_list ap;
C does not provide any mechanism to allow a called function to determine how many arguments were provided. The mechanism must be part of the calling interface.
For example, printf relies on the % format specifications, while execv requires the caller to place a null pointer as the last argument.
A varargs function can be called with no variable arguments, but the caller must not attempt to access any variable argument in that case. For example, the mode argument to the Posix open() function is only consulted in the case that a new file is created, so it need not be supplied if the flags argument doesn't contain the O_CREAT flag (or some other extension flag, such as O_TMPFILE in Linux, which requests file creation).
The variable-length part of the prototype must follow at least one fixed argument. So it is not possible fir a varargs function to be called with no arguments at all.
Can you have in C variable length arguments functions with cases when you don't want to pass any variable?
Yes. In modern C, Code cannot define a ... function with no arguments, yet you can call such a function with no arguments by declaring the a function without function signature. In that way the function can be called with zero arguments.
The function still needs some way to understand the count of arguments. This is often done with the first argument as a count (or format) or a final argument as a sentinel.
Given "will have passed only char*"...
int foo_count(int counter, ...);
// zero usage example
foo_count(0);
int foo_sentinel(char *s);
// zero usage example
foo_sentinel((char*) NULL);
To do so with passing no arguments, the count needs to be conveyed in some other fashion, perhaps with a global variable - although this is not recommended. (Better to simply pass the count.)
Declare function:
int foo_count;
int foo(); // no prototype
Call function
foo_count = 0; foo()
foo_count = 1; foo("one")
foo_count = 2; foo("one", "two")
Define the function
int foo(char *s1, ...) {
if (foo_count > 0) {
va_list ap;
va_start(ap, s1);
puts(s1);
for (int i=1; i < foo_count; i++) {
puts(va_arg(ap, char *));
}
va_end(ap);
}
}

Enforcing ending variadic function parameters with NULL

Is it possible to make declaration of variadic function so that it doesn't end with "..."?
Today I learned more about exec from unistd.h but through the day I've seen three (two actually) different declaration of execl:
1) int execl ( const char * path, const char * arg0, ..., (char*)NULL ); was shown to us in school and I imagined I would have to end the function call with a NULL value
2) int execl(const char *path, const char *arg, ... /* (char *) NULL */); is what I've found in the exec(3) man page. That would probably mean I still have to end it with a NULL value, but it is not enforced.
3) int execl(const char *path, const char *arg, ...); is what I found here. This one would probably normally put me to rest with the first one being a simplification for students, the second was a varning and this is the real thing (even though I would probably have normally higher regard for both options one and two.)
But then I found on the same site this declaration:
int execle(const char *path, const char *arg, ..., char * const envp[]);
Same question applies, I was unable to create variadic function not ending in ... with gcc telling me that it's expecting ')' before ',' token pointing to the comma after the three dots.
So finally, is it possible to make variadic functions ending with a NULL characters (execl) and if not, is it possible to make it end with predefined variable (execle)?
I tried to compile with gcc 6.3.1, I also tried --std=c11.
Is it possible to make declaration of variadic function so that it doesn't end with "..."?
Is it possible is a slippery question, but consider these facts:
the standard says that "If a function that accepts a variable number of arguments is defined without a parameter type list that ends with the ellipsis notation, the behavior is undefined" (C2011, 6.9.1/8)
Perhaps that answers the question already, but if you choose to mince words and focus on function declarations that are not definitions, then
a function definition is also a declaration
the C language standard requires all declarations of the same function to be "compatible" (else program behavior is undefined) (C2011 6.7/4)
two function declarations with mismatched parameter lists are not compatible (C2011, 6.2.7/3)
Thus, if you declare a variadic function that in fact is also defined, and that function's parameter list does not end with ..., then the program's behavior is undefined.
The documentation you've been reading for execle() and execl() is written to express and discuss those functions' expectations, but to the extent that it seems to present variadic function declarations in which the last element of the parameter list is not ..., those are not actually valid C function declarations.
So finally, is it possible to make variadic functions ending with a NULL characters (execl) and if not, is it possible to make it end with predefined variable (execle)?
It is not possible to describe such calling conventions via conforming C declarations. Variadic functions can have such expectations, and can enforce them at runtime, but they can be enforced at compile time only by a compiler that relies on special knowledge of the functions involved, or on C language extensions that allow such constraints to be described.
The declaration of a variadic function can only specify the required arguments, and the compiler can enforce their types. The variable-length part never has any type checking done. And the variable-length part is always at the end. The declaration for execle() is not meant as an actual C declaration, but just to describe to the programmer how he should construct the arguments.
It's not possible to enforce that the last argument to execl() is NULL. Variadic functions don't know how many arguments were supplied, they determine it from the values of the arguments. printf() assumes that it has enough arguments to fill in all the operators in the format string, and execl() iterates through the arguments until it finds NULL (execle() is similar, but it reads one additional argument to get envp). If you don't end with NULL, it will just keep going, reading garbage and causing undefined behavior.
The declaration you see is the one in the man pages of execl. The declaration for execle in glib is the following: int execle (const char *path, const char *arg, ...). The implementation assumes the last argument is a char**, and uses it for envp. I don't think you can enforce such a rule in C.

Calling function with variable arguments dynamically

Is there a possibility to call function with variable arguments from the C code dynamically?
For example I have text file which contains data (written using this scheme: function_name arguments) for example:
func1 1 2 3
func2 1
func3
My program written in C is parsing this file and looks in a populated array (which holds function name in string and target native function pointer) for function with given name by comparing the string and calls a pointer of this function with arguments from the text file. For example functions like that:
void func1(int a, int b, int c) { }
void func2(int a, int b) { }
void func3() { }
The problem is that even if I know the number of arguments, I don't know how to write in C function pointer call with dynamic number of arguments. Is there a possibility to populate va_list (I know that this is NOT a container or a typical array!) then pass to the native function or any other way to do this? The only way which came into my mind is populating dynarec block with x86 code for calling native function with variable arguments, but it's not a clean solution. Is such thing even possible in plain C?
If it is hard to understand just write and I'll try to explain better. And if you want to write "use va_list" - then read carefully my post once again.
Thanks in advance.
I'm self answering, because this will be a solution for other people. If you want to call functions with variable arguments dynamically without writing direct machine code just use avcall library from FFCALL. Quick reference guide of avcall library can be found here. It's a crossplatform library that makes this possible. For example to call function named func1 with return type void which takes three arguments and all of them are of type int just do this:
#include <avcall.h>
int a = 1, b = 2, c = 3;
av_alist alist;
av_start_void(alist,&func1);
av_int(alist,a);
av_int(alist,b);
av_int(alist,c);
av_call(alist);
You can of course use this for functions which returns value or takes arguments of different type, for more just look at avcall library manual page. :)
I like your way of thinking, because obviously, you are a true hacker, but...
do not try to do it like this.
The proper way of doing this is to go alter these functions so that each one of them accepts an array of int instead of individual int parameters. But I suppose that if you had the freedom to change them, you would have done it already and you would not be asking.
The next best way of doing it is to write a number of functions, conv1(), conv2(), conv3() etc, each accepting an array of int, and a pointer to a function which accepts individual int parameters. So, convN() accepts an array of N integers, and a pointer to a function which accepts N individual int parameters. It reads each int from the array and passes it to the function as a parameter. It can do this, because it has been specifically written to work with a function of precisely that number of parameters. Then, in your table with function names and pointers to functions, add a pointer to the right convN() function, depending on the number of parameters that the target function expects.
Don't hack it.

Interoperability of C variadic function and Fortran

Is there a way to declare a C variadic function and call it from Fortran?
I need to call this function to compute some dot products between vectors labeled with a string.
My idea was to declare something like the following, where the variable list of arguments contains string literals. If the variable list of arguments is empty, then I would do a lookup among the standard labels and perform the calculation. If the user specified two labels I would retrieve those two vectors and get their dot product:
extern "C" void compute_dot_product(double * dot_product, ...)
{
va_list args;
va_start(args, NULL);
char * label1 = va_arg(args, char *);
if (!label1)
{
// Do standard label lookup and compute dot product
}
else
{
// Compute dot product between the vectors with the specified labels
char * label2 = va_arg(args, char *);
}
va_end(args);
}
the only problem is that I can compile my C library and link it to a Fortran executable, but I get a runtime error when I try to access the variable list of arguments.
Any idea if what I am trying to do is possible?
A possible solution would then be to split into two functions: one that does the standard label lookup (0 argument case), the other that handles the non-standard label lookup (2 argument case). I would rather avoid this solution though.
It is not possible to call a variadic function in a standard conforming (i.e. portable) way.
You could make the definition of the C function take two parameters only (so it is no longer variadic - existing references to the function would need to be modified), with the second parameter in the C function a pointer, either NULL to indicate that there are no additional things being passed, or pointing at an array of pointers (perhaps NULL terminated) or whatever, with any additional things. In F201X an interface body for this sort of function might be able to use the OPTIONAL attribute for the second argument.

Pass a string containing a function name and its arguments to another function.

I would like to pass a string to a function in C in which the function will parse out a function name, the arguments for the function, and its datatypes, and then call the function for me. What is the best approach?
If you want to write a function with a format string and variable arguments like:
int function(const char* strFormat, ... )
{
//parse out the format using regex or something
//then store the data into the variable aruments
//or create a string concatenating everything
}
like, say printf, sprintf, or scanf does,
then the best thing for you to do is look at some good tutorials.
http://msdn.microsoft.com/en-us/library/fxhdxye9(v=vs.80).aspx
http://www.cprogramming.com/tutorial/c/lesson17.html
If you are wanting to actually pass a function name for the function to call, along with its arguments, you either need to implement some form of reflection or introspection in your c code, a really complex switch statement which calls the functions for you based upon the string value, or write some complex macros to act as a sort of a secondary
compiler.
glib's gobject is an excellent example of introspection in c.
http://developer.gnome.org/gobject/stable/
something simple without introspection may be:
void* function (const char* strFunctionName, ... )
{
if(!strcmp(strFunctionName, "functionA"))
{
//use va_list to parse out the arguments for the function.
functionA(//each of the arguments from va_list);
}
else if(!strcmp(strFunctionName, "functionB"))
{
//use va_list to parse out the arguments for the function.
functionB(//args from va_list);
}
...
}
If you have something more specific in mind, please specify in your question.
I'm not sure if this is standard, but you could use __PRETTY_FUNCTION__ in C++.
e.g:
void foo(int a, int b)
{
cout << __PRETTY_FUNCTION__ << endl;
}
outputs:
void foo(int, int)
If you want to make:
char *funct = "foo(bar)";
to actually call the function foo(), then its impossible, C just doesn't work that way. I would recommend that:
a) you sit down and rethink your application, because such behaviour shouldn't be needed for anything.
b) try a language with such capabilities, such as objective-c
c) if you really, really, really wanna do it... then make a string parser and lots of if's, or function pointers. Something in the lines of:
Get string in the form of "function(var1, var2, ..., varN)"
Get the name of the function (ie. everything before '(' )
Get all the parameters (strtok() for example)
Identify the function comparing constant names with your string ( strcmp() )
If the parameters are numeric ( isdigit() or sscanf( string, "%d", &parameter ) > 0 ) convert them to a usable primitive (atoi(), atof(), etc or sscanf())
Pass the params to your function.
If you want to execute a code from a string (I'm just guessing, your question is hard to understand), then there are many options available: from embedding the whole Clang and LLVM into your code (and making sure its JIT is aware of all your declarations you're going to export) to embedding a simple scripting language (like Lua or Guile) and providing wrappers for all the functions you want to call this way.

Resources