I am working on porting a C FIFO queue implementation into my code and I don't feel comfortable including functions that I don't understand. What does this function do? I see that it returns an integer value, but I don't know what it means. What is the (*iter) parameter? I don't see this type declared in the header or implementation file.
You can find the header hereYou can find the implementation here
The function in question is copied below:
int fifo_iter(fifo_t *f, int (*iter)(void *data, void *arg), void *arg)
{
fifonode_t *fn;
int rc;
int ret = 0;
for (fn = f->f_head; fn; fn = fn->fn_next) {
if ((rc = iter(fn->fn_data, arg)) < 0)
return (-1);
ret += rc;
}
return (ret);
}
int (*iter)(void *data, void *arg) is a function pointer. When you call fifo_iter, you pass it a callback function in the second parameter. This function must have a signature like:
int my_callback(void* data, void* arg)
This function will then be called for every item in the fifo_t. It will be passed the fn_data member in the data argument. Whatever you pass for arg to fifo_iter will also be passed to iter as his arg argument. This is a common way to just pass generic "context" information through to the callback, without having to resort to ugly, thread-unsafe global variables.
So you can use it like this:
int my_callback(void* data, void* arg) {
printf("my_callback(%p, %p)\n", data, arg);
return 0; // always continue
}
void test(void) {
fifo_t myfifo; // Needs initialized and populated...
fifo_iter(&myfifo, my_callback, NULL);
}
Additionally, we see that it uses the return value of iter in a special way. First of all, if iter ever returns a negative value, the iteration stops immediately, and fifo_iter returns -1. This can be an "early failure". Otherwise, it accumulates the (positive) return values into ret, and then returns that value.
Expanding my example. This assumes that the fifo fn_data members point to strings. This will count the total number of capital and lowercase letters in all strings in the FIFO, and also return the total length of all strings.
// The context that we'll maintain during the iteration
struct my_context {
int caps;
int lowers;
};
// The callback function, called for every string in the FIFO.
int my_callback(void* data, void* arg) {
const char* str = data; // Node data is a string
struct my_context *ctx = arg; // Arg is my context
// If any string in the FIFO has a !, abort immediately.
if (strchr(str, '!'))
return -1;
// Update the context to include the counts for this string
ctx->caps += count_capital_letters(str);
ctx->lowers += count_lowercase_letters(str);
// fifo_iter will accumulate this length
return strlen(str);
}
// Test driver function
void test(void) {
fifo_t myfifo;
struct my_context ctx;
int total;
// Assuming these functions exist:
fifo_init(&myfifo);
fifo_append(&myfifo, "Stack");
fifo_append(&myfifo, "Overflow");
// Initialize the context
ctx.caps = 0;
ctx.lowers = 0;
// Iterate over myfifo, passing it a pointer to the context
total = fifo_iter(&myfifo, my_callback, &ctx);
if (total < 0) {
// Any string had a '!'
printf("Iteration failed!\n");
return;
}
printf("total=%d caps=%d lowers=%d \n", total, ctx.caps, ctx.lowers);
}
If you take a gander through the Linux kernel source code, you'll see this construct all over the place.
For a simple FIFO like we have here, it may not seem worth it. But when you're dealing with more complex data structures like hash lists, and RCU lists, it makes more sense to maintain the iteration logic in just one place, and utilize callbacks to handle the data in whatever way you need to.
It is iterating over the structure, calling the argument function iter() on each element; if an element returns negative, the iteration stops and -1 is returned.
Related
I'm working on a project and I have a list of functions to use.
I use the provided DLL.
I have the function's prototypes in the file "list.h".
This file is also provided to me
list.h
typedef unsigned short (__stdcall * ReadConfig)
(void * * pDataOut,
size_t * pSizeDataOut);
I wrote this main.c
int main (int nbArg, char** listeArg)
{
// Initialization
unsigned short outputFunction;
void * pointerMemoryZone = NULL;
size_t sizeMemoryZone = NULL;
// Load DLL
HMODULE dllLoadOuput= LoadLibrary("dllFile");
// Alias Creation
typedef unsigned short(*A_ReadConfig) (void * *, size_t *);
// Get Pointer on Function
A_ReadConfig ptrReadConfiguration = (A_ReadConfig)GetProcAddress(dllLoadOuput, "ReadConfig");
// Launch of the function
outputFunction = ptrReadConfiguration(&pointerMemoryZone, &sizeMemoryZone);
// Display
printf("\n\nSize Read Config : %ld\n\n", sizeMemoryZone);
// Unload DLL
FreeLibrary(dllLoadOuput);
return 0;
}
This program works and I get the size of the memory area fine.
But my program, my variables are they correctly declared and used...?
And how can I read the data contained in the memory area...?
Below is a diagram provided in the documentation :
Presumming outputFunction indicates success, the pointer pointerMemoryZone should contain sizeMemoryZone bytes of data.
How you access the data depends on the format (e.g. text/json/xml string).
A sample loop to display the data in ascii and hex:
for(int i=0; i<sizeMemoryZone; i++) {
char c = ((char*) pointerMemoryZone)[i];
printf("%c{%x} ", c, c);
}
I answer to my question. I find a solution.
I have to read datas byte by byte.
So I create a caracter pointer on "pointerMemoryZone" (wich contains adress of datas) by forcing the pointer type to character (because 1 byte)
And I make a loop in which I loop through the addresses one by one (along the length of the data)
Below the code for the loop
//...
//...
//...
// Launch of the function
outputFunction = ptrReadConfiguration(&pointerMemoryZone, &sizeMemoryZone);
// Creation of Pointer
char *pointerOnPointerMemoryZone = NULL;
// Begin Loop
for (int i = 0; i < sizeMemoryZone; i++)
{
// Association Pointer to Adress (+0, +1, +2, etc..)
pointerOnPointerMemoryZone = (char*)pointerMemoryZone + i;
printf("\n%d\t\t%d\t\t%c",i, *pointerOnPointerMemoryZone, *pointerOnPointerMemoryZone);
}
// End Loop
//...
//...
//...
I was working on the following as an example to see the differences between passing an object directly and then passing a pointer to it:
#include "stdio.h"
// Car object
typedef struct Car {
char* name;
unsigned int price;
} Car;
void print_car(Car car) {
printf("<Car: %s, Price: $%d>", car.name, car.price);
};
void print_car2(Car *car) {
printf("<Car: %s, Price: $%d>", car->name, car->price);
};
int main(int argc, char* argv[]) {
Car chevy = {chevy.name = "Chevy", chevy.price = 45000};
print_car(chevy);
Car mazda = {chevy.name = "Mazda", chevy.price = 30000};
print_car2(&mazda);
return 1;
}
Other than the first approach being much more readable and easier to understand for me, what are the differences between the two? When would passing a pointer be the only option, and why do both work in the above case?
There are two reasons to use the second approach:
If you want to avoid copying the whole struct. If the struct is big, this can affect performance.
If you want to modify struct that you're passing.
In general (not only for structs) passing a variable to a function will make a copy of this variable so if you want to alter this variable you ll have to return the value of the altered copy but you may want to alter the variable and return something else, in this case you have no other choice of passing a pointer as argument exemple :
first exemple with passing a variable
int useless_func(int nb) /*nb is actually a copy of the variable passed as argument */
{
nb++; /* the copy was incremented, not the real variable */
return nb; /* the new value is returned */
}
int main()
{
int nb = 1;
useless_func(nb); /* here nb is still = 1 cause it wasn't altered by the function */
nb = useless_func(nb); /* here nb is = 2 cause it took the return value of the func */
}
now a second stupid exemple with pointer :
char *useless_func(int *nb) /* nb is now a pointer to the variable */
{
*nb++; /* the derefencement of the pointer (so the variable value) was incremented */
return strdup("This is a useless return"); /* we return some other stupid stuff */
}
int main()
{
int nb = 1;
char *str = useless_func(&nb); /* now nb is = 2 and str is an allocated useless string woohoo */
}
When a function is called, the arguments in a function can be passed by value or passed by reference.
void print_car(Car car)
In here you are directly passing an object to the function, that means it will be copied into the functions stack and destroyed after function call ends. This method should be avoided because copying is expensive and unnecessary. Also if your objects are quite big, this operation will take a lot of time
void print_car2(Car *car) {
In this situation you are passing a pointer to the object which is called pass by reference, that means you are working with the original object and changes you make will directly affect it. It's a lot faster because you are not moving your object, but you should be careful about alter of original data
/*
//i comment this block, please see the updates
void* fun_one(char *buffer, long length)
{
if(NULL == buffer)
return xxx; //return what value here
...
}
fun_two()
{
...
fun_one(image->buffer, image->length);
...
}
*/
If the error happened, I do not hope to exit the program but return to fun_two(). What should I do?
I know that return (void *)0; or return NULL;when succeed, but return what value when error?
links related:
void *
update:
but what if ti's a thread function ,such as
int main()
{
...
pthread_create(&id1, NULL, (void*)myThread1, ¶m_struct);
...
}
void* myThread1(void* param)
{
struct len_str* img = (struct len_str*)param;
if(NULL == img->buf)
return xxx; //return what value here
if(0 == img->len)
return xxx;
...
}
links related:
pthread_create
the return value of myThread1() is void *
what value should return if the error occur
Instead of returning a pointer, return a value of int type.
A return of 0 means all ok.
A return of 1 means NULL pointer passed in.
A return of 2 means invalid length.
...
int fun_one(char *buffer, long length) {
if (buffer == NULL) return 1;
if (length == 0) return 2;
if (length < 0) return 3;
/* ... */
return 0;
}
For extra clarity (???), you can use enums
enum fun_one_errors {FO_OK, FO_NULL, FO_ZERO, FO_NEG};
return FO_ZERO;
You are struggling with the "design" of your interface. What do you need to pass to the function, what does it need to return and how do you signal an error.
Normally if you return a pointer, the pointer value zero (NULL) means an error. If you want to pass more information, you can use an auxiliary variable that you set to one of your error codes. This will be a global variable or a (pointer to) a variable:
int my_errcode;
...
if ((p=fun_one(buf, len))==NULL) printf("error %d\n",my_errcode);
As an alternative, you return the void * pointer as a parameter (you must use a double indirection now) and let the function return signal success, or failure and the type of failure:
if ((my_errcode=fun_one(buf, len, &p))!=0) printf("error %d\n",my_errcode);
So it is up to you...
In your thread function, you would dynamically allocate a variable to store the return value. You would set that value and return the pointer.
Then when you call pthread_join, you'll receive the pointer to that variable, which you would then cast and dereference to read the value, and free it when you're done.
void* myThread1(void* param)
{
int *rval = malloc(sizeof(int));
if (rval == NULL) {
perror("malloc failed");
exit(1);
}
struct len_str* img = (struct len_str*)param;
if(NULL == img->buf) {
*rval = 0;
return rval;
}
if(0 == img->len) {
*rval = 1;
return rval;
}
...
}
int main()
{
...
pthread_create(&id1, NULL, (void*)myThread1, ¶m_struct);
...
void *rval;
pthread_join(id1, &rval);
printf("rval = %d\n", *(int *)rval);
free(rval);
}
Well, when returning a pointer you have normally the problem of what to do if the function execution resulted in an error?
The classical approach is to reserve a special value (NULL, or 0 in C++) to represent this kind of error, and use a global to represent the different error values you can have.
But, what if you want a reentrant module to be able of multithreading? Well, the pointers have the problem that everywhere they point to is a possible source of trouble if that place happens to be occupied by a non-useless variable.
But we have a different approach. Just create dumb variables (not used for anything else) to hold the addresses of nothing. This way you can reserve several pointer values (the addresses of those variables) to represent the proper error codes. As the places they have been located by the compiler cannot be used for anything else, they can be used to hold (not to store) the address of something special to you.
int error_001_placeholder;
int error_002_placeholder;
int error_003_placeholder;
...
if (condition_1) return &error_001_placeholder;
if (condition_2) return &error_002_placeholder;
if (condition_3) return &error_003_placeholder;
Then, you'll be able to check for different invalid return pointers, just by checking if they belong to this set of pointers.
Even more, if you want to do generic error check, you can reserve a global array, and return individual cells for different errors, finally to generic check if the returned value is an error, you can just check if
returned_value >= errors_array && returned_value < errors_array + erros_array_size.
I have been rewriting some of my functions to return int instead of structs so that I can do this
if ( function(&struct1,vars) != 0 )
{
// die and give error
}
instead of:
struct = function(vars);
I am however missing some concept here as whenever i try to access a value of my struct in the main, I do not get the value that was assigned to it in the function. I would greatly appreciate if someone could explain to me what exactly happens (I will write what I think that happens) to my memory/variables and why it doesn't work.
Main (shortened):
int main (int argc, char *argv[]) {
arguments args;
data data;
scan scans;
printf("Value at start %i\n",scans.number);
if (scan_extractor(&args,&scans) != 0) // Pass the reference of the struct to scan_extractor (while still being un-initilizaed, something I don't quite grasp).
{
printf("Error in argument reader\n");
exit(0);
} else {
printf("Main thinks %i scans\n",scans.number);
}
return(0);
}
function (scan_extractor):
int
scan_extractor(arguments* args, scan* scans)
{
FILE* fr;
int counter = 0;
fr = fopen(args->scans,"r");
scans = calloc(MAX,sizeof(scan)); // Allocate memory to store multiple instances of the scan object
while (fgets(mzML_buffer,MAX_BUFFER,fr) != NULL)
{
(scans+counter)->id = atoi(mzML_buffer); // Modify the global version of scans
counter++;
}
scans->number = counter;
printf("Function read %i scans\n",scans->number);
return(0);
}
The file that is read contains 1 line containing the value 1
The output that i get is:
Value at start 32767
Function read 1 scans
Main thinks 32767 scans
Why this drives me crazy is that a near identical chunk of code that contains the input parameters is accessible from main using similar syntax (only char* value of struct arguments vs int value of struct scans).
scan_extractor(arguments* args, scan* scans)
scans = calloc(MAX,sizeof(scan));
You are allocating memory to the copy of the pointer being passed. To be able to allocate memory to a pointer inside the function. You need to pass the pointer by reference:
scan_extractor(arguments* args, scan** scans)
*scans = calloc(MAX,sizeof(scan));
On second thoughts. Your program doesn't make sense. You are mixing two concepts.
You allocate a scan object on local storage and pass its address to the function. While inside the function you allocate dynamic memory to the function local to the pointer, which was previously pointing to the object passed. This simply leaks memory while Your stack based scan object never gets populate
Basically, You only need to pass the address of object and use that object. It is already allocated no need for allocations inside the functions.
scan scans;
if (scan_extractor(&args,&scans)
scan_extractor(arguments* args, scan* scans)
scans->number = counter;
You need a second level of indirection in order to return an allocated unit. The function scan_extractor should look like:
int scan_extractor(arguments* args, scan** scans)
{
FILE* fr;
int counter = 0;
fr= fopen(args->scans,"r");
*scans = calloc(MAX,sizeof(scan));
while (fgets(mzML_buffer,MAX_BUFFER,fr) != NULL)
{
((*scans)[counter]).id = atoi(mzML_buffer); // Modify the global version of scans
counter++;
}
(*scans)->number = counter;
printf("Function read %i scans\n",(*scans)->number);
return(0);
}
Looking at this code somehow tells me that the lines (*scans)->number = counter; and printf("Function read %i scans\n",(*scans)->number); are wrong anyway but I can't tell this without known the scan structure. I think I can guess the intention (storing the number of scans). I recommend to solve this differently by a slightly modified approach:
typedef struct scanlist {
unsigned int count;
scan *scans;
}scanlist;
...
int scan_extractor(arguments* args, scanlist* scans)
{
scans->scans = calloc(MAX,sizeof(scan));
...
while (...) {
scans->scans[counter].id = ...
}
...
scans->count = counter;
Otherwise you are wasting memory with a number field not needed for every scan.
Given a C-string: how would I be able to write a function that will get the next token in the string, and a function that will peek the next token and return that without using global variables?
What I'm trying to do is have a static variable that will hold the string, and when called, it would just increment a pointer, and it will reset that static variable throwing out the token that has been retrieved. The problem is: how would I be able to differentiate between the first call (when it will actually store the string) and the other calls, when I am just retrieving it?
Any thoughts on this?
EDIT:
Here's what I have now that "works" but I want to make sure that it should actually work and its not just a coincidence of a pointer being null:
char next_token(char *line) {
static char *p;
if (p == NULL)
p = line;
else {
char next_token = p[0];
p++;
return next_token;
}
}
The code in your edit is wrong. You are handling the NULL case incorrectly.
I initially answered in terms of emulating strtok which seemed to be what you wanted, but you have clarified that you want single characters.
The if-condition should be:
if (line != NULL) p = line;
And you presumably remove the else so that code executes every time... Unless you don't want a result on the first call (you should at least return a value though).
You call like this:
char token = next_token(line);
while( 0 != (token = next_token(NULL)) ) {
// etc
}
typedef struct {
char* raw;
// whatever you need to keep track
} parser_t
void parser_init(parser_t* p, char* s)
{
// init your parser
}
bool parser_get_token(parser_t* p, char* token)
{
// return the token in "token" or return a bool error ( or an enum of various errors)
}
bool parser_peek_token(parser_t* p, char* token)
{
// same deal, but don't update where you are...
}
You have a couple of choices. One would be to use an interface roughly like strtok does, where passing a non-null pointer initializes the static variable, and passing a null pointer retrieves a token. This, however, is fairly ugly, clumsy, error-prone, and problematic in the presence of multithreading.
Another possibility would be to use a file-level static variable with separate functions (both in that file) to initialize the static variable, and to retrieve the next token from the string. This is marginally cleaner, but still have most of the same problems.
A third would be to make it act (for one example) like a file -- the user calls parse_open (for example), passing in the string to parse. You return an opaque handle to them. They then pass that back to (say) get_token each time they want another token.
Basically, there are three ways of a function to pass information back to its caller:
via a global variable
via the return value
via a pointer argument
And, similarly there are ways for the function to maintain state between calls:
via a global or (function-)static variable
by supplying it as a function parameter and returning it after every call
via a pointer argument.
A nice coding convention for a lexer/tokeniser is to use the return value to communicate the number of characters consumed. (and maybe use an extra pointer variable to pass the parser state to and fro calls)
This is wakkerbot's parser:
STATIC size_t tokenize(char *string, int *sp);
Usage:
STATIC void make_words(char * src, struct sentence * target)
{
size_t len, pos, chunk;
STRING word ;
int state = 0; /* FIXME: this could be made static to allow for multi-line strings */
target->size = 0;
len = strlen(src);
if (!len) return;
for(pos=0; pos < len ; ) {
chunk = tokenize(src+pos, &state);
if (!chunk) { /* maybe we should reset state here ... */ pos++; }
if (chunk > STRLEN_MAX) {
warn( "Make_words", "Truncated too long string(%u) at %s\n", (unsigned) chunk, src+pos);
chunk = STRLEN_MAX;
}
word.length = chunk;
word.word = src+pos;
if (word_is_usable(word)) add_word_to_sentence(target, word);
if (pos+chunk >= len) break;
pos += chunk;
}
...
}