C Function pointer parameter not the same when function exits - c

I am having a problem with passing a pointer to a function. When the function returns the pointer seems to be different than what it is in the function.
So I pass a pointer to the function which gets raw image data which should then be stored in the memory referenced by the pointer.
If I then pass the pointer from inside the raw image function to a function to create a JPEG file from the raw data then it works correctly.
If I first wait for the raw image function to finish and then call the JPEG function using the pointer I passed to the raw image function then it fails to create the image.
A simplified version of the code is below:
int getRawImage(unsigned char *pBuffer);
int writeJPEGBFile(unsigned char *idata, char *ofile);
int main(int argc, char** argv) {
unsigned char *rawData = NULL;
char filename[MAXPATHLEN] = "/home/user/tst/img.jpg";
getRawImage(rawData);
// This does not work
writeJPEGBFile(rawData, filename);
free(rawData);
return 0;
}
int getRawImage(unsigned char *pBuffer) {
void *hDevice;
hDevice = scanOpenDevice();
// Removed code for simplification
scanGetFrame(hDevice, pBuffer, NULL)
scanCloseDevice(hDevice);
// This Works!!
//char filename[MAXPATHLEN] = "/home/user/tst/img.jpg";
//writeJPEGBFile(pBuffer, filename);
return 0;
}
int writeJPEGBFile(unsigned char *idata, char *ofile) {
// JPEG code goes here
return 0;
}
My question is what am I doing wrong and how can I pass the rawData pointer to the writeJPEGBFile() function successfully in the main() function?
The definition for scanGetFrame() is as follows:
typedef void *FTR_PVOID;
FTR_API_PREFIX FTR_BOOL FTR_API ftrScanGetFrame( FTRHANDLE ftrHandle, FTR_PVOID pBuffer, PFTRSCAN_FRAME_PARAMETERS pFrameParameters );
The scanGetFrame() function comes from a 3rd party library that I am linking with so I will not be able to change the definition.

Given that rawData is a null pointer in main(), you almost certainly need to revise the interface to getRawImage() so that it takes a char ** and you pass &rawData to it. You also need to think about how the calling code will know how big the data is.

I managed to work it out. Thanks to all for the pointers which led me to the solution:
int getRawImage(unsigned char *pBuffer);
int writeJPEGBFile(unsigned char *idata, char *ofile);
int main(int argc, char** argv) {
unsigned char *rawData; // Removed the NULL assignment
char filename[MAXPATHLEN] = "/home/user/tst/img.jpg";
// Set the size of rawData - loadImageSize() sets the value of the ImageSize class variable.
loadImageSize();
rawData = (unsigned char *) malloc(ImageSize.nImageSize);
getRawImage(rawData);
// This works now
writeJPEGBFile(rawData, filename);
free(rawData);
return 0;
}
int getRawImage(unsigned char *pBuffer) {
void *hDevice;
hDevice = scanOpenDevice();
// Removed code for simplification
scanGetFrame(hDevice, pBuffer, NULL)
scanCloseDevice(hDevice);
return 0;
}
int writeJPEGBFile(unsigned char *idata, char *ofile) {
// JPEG code goes here
return 0;
}

Related

calling function by value in C

I am new to C language somehow and I am trying here to call a function "func" in main function but it gives me compiling error. I tried to search for examples similar to this situation in Google but stil getting errors.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
struct str {
int value;
uint32_t ptr_next;
};
void func(int arg, char* arr[]);
int main() {
int Arg;
char* Arr[1];
func(Arg, *Arr[1]);
return 0;
}
void func(int arg, char* arr[]) {
int list;
struct str r;
FILE* file = fopen(arr[1], "rb");
do {
list = fread(&r, sizeof(struct str), 1, file);
if (list > 0)
printf("%d ", r.value);
fseek(file, r.ptr_next, 0);
}
while ((r.ptr_next != 0) && (list > 0));
}
The question is how can I call functions by value in C language?
C only supports calling functions by value, calling by reference was added in C++ and uses the & symbol.
The value you are passing to the function is a location in memory, a pointer. If you want to hand to the function a copy of the data at that memory location you'll need to make a copy for it.
// Assuming that Arg and Arr are initialized.
char* Arr2[]; // Make a storage place for the char**.
Arr2 = malloc(Arg*sizeof(char*)); // Make the right number of char*s in it
for(int e=0; e<Arg; e++) { // For each elem in the main array:
Arr2[e]=malloc(sizeof(char)*strlen(Arr[e])); // Make space for the chars,
strcpy(Arr2[e],Arr[e]); // And copy them.
}
Side note
You haven't initialized Arg or Arr in main. I suspect that you might have meant the command line parameters.
int main(int Arg, char* Arr[])

Passing String Pointer Array in C

I have a simple C function which I would like to pass an array of pointers to various strings. I am having trouble with the compiler barking at my function call parameters. Here is simple representation of what I am doing,
myfunction.h
int myServices(int, char *[]);
myfunction.c
#include <myfunction.h>
int myService(int value, char *strpointer[]) {
***
}
mainroutine.c
#include <myfuntion.h>
void main () {
// Initialize Parameters
int result;
int stringcnt;
char string1[8] = "-st";
char string2[8] = "-ir";
char * stringptr[10];
// Initialize stringptr
stringptr[0] = string1;
stringptr[1] = string2;
stringcnt = 2;
// Call Service
result = myService(stringcnt, stringptr); <== gcc issue with stringptr
}
The C compiler keeps giving me a "invalid use of member (did you forget the '&'?" with the stringptr in the myService call. I tried '&' and '*' with stringptr in the myService call in the main routine with no luck. Any ideas.
I ran your code and notices a few things: first of all in your header file you didn't define the arguments properly (case of the missing coma), and likewise your main entry point did not have the proper return type (needs to be int) nor arguments (int argc, char *argv[]). I've made the changes and attached them below:
// func.h
int myService(int, char*[]);
Then the function code:
// func.c
#include "func.h"
int myService(int value, char *strpointer[]) {
// your code here
return 0;
}
// prog.c
-
#include "func.h"
int main (int argc, char *argv[]) {
// Initialize Parameters
int result;
int stringcnt;
char string1[8] = "-st";
char string2[8] = "-ir";
char * stringptr[10];
// Initialize stringptr
stringptr[0] = string1;
stringptr[1] = string2;
stringcnt = 2;
// Call Service
result = myService(stringcnt, stringptr);
return 0;
}
I compiled this using the command gcc -o prog.o prog.c func.c with no errors and smooth execution. Hope this works for you

Block signature for block that takes a function pointer and returns a block

I am using clang on linux.
What is the correct way to format this block?
(int ^(int, char**)) (^f2b)(int, char**) = (int ^(int, char**)) ((int (*func)(int, char**)))
{
return int ^(int argc, char** argv){ func(argc, argv)};
};
I am getting an error
error: type-id cannot have a name
int (^f2b)(int, char**) = (int ^(int, char**)) ((int (*func)(int, char**)))
The error underlines (*func).
I am trying to create a block that takes in a function pointer named func as a parameter and returns a block that calls that func using the arguments it is passed.
The key is the Block_copy function from <Block.h>1. That puts a copy of a block on the heap, which allows the block to be returned.
#include <stdio.h>
#include <Block.h>
typedef int (^block_t)(int, char **);
typedef int (*func_t)(int, char **);
block_t (^createBlock)(func_t func) = ^(func_t func)
{
return Block_copy( ^(int argc, char **argv) { return func(argc, argv); } );
};
int showFirst(int argc, char *argv[])
{
printf("%s\n", argv[0]);
return argc;
}
int main(void)
{
int argc = 3;
char *argv[] = {"hello", "world", NULL};
block_t block1 = createBlock(showFirst);
int count = block1(argc, argv);
printf("count=%d\n", count);
Block_release(block1);
}
createBlock takes a function pointer as its argument, and returns a block with the signature int (^block)(int, char **).
showFirst is just one possible implementation of the function that can be passed to createBlock. It displays the first string in the argv array and returns the value in argc.
The main function creates a block from the showfirst function. It then invokes the block, prints the returned value, and releases the block.
The output from the code is:
hello
count=3
1 I was not aware of <Block.h> until reading OP's answer.
http://thirdcog.eu/pwcblocks/ helped a lot.
#include <stdlib.h>
#include <stdio.h>
#include <Block.h>
int fake_main(int argc, char** words)
{
printf("%s\n", (char*)words);
return argc;
}
int main(int argc, char* argv[])
{
typedef int(*main_type_func)(int, char**);
typedef int(^main_type)(int, char**);
typedef main_type(^f2b_type)(main_type_func);
f2b_type f2b = ^ (main_type_func func)
{
return Block_copy(^ (int apple, char** ban)
{
return func(apple, ban);
});
};
printf("%d\n", f2b(fake_main)(1, "words worked"));
}
This is a minimum example of accomplishing the goals I outlined in the question.
The trick is the typedefs. Simplify the type signature by creating typedefs to help. I recommend that you use these whenever you want to accept and/or return a function pointer/block pointer.
Block_copy() moves the block from the stack into the heap.
It would be more correct to save the block pointer returned from
f2b(fake_main)
Then after use call
Block_release()
On it.
Your type syntax is incorrect. Based on your usage, I'm guessing you are declaring f2b to be a pointer to a block, which takes a pointer to a function that takes an int and a char ** and returns an int, and the block returns another block that takes an int and a char ** and returns an int.
The proper syntax for that declaration would be:
int (^(^f2b)(int (*) (int, char **)))(int, char **)
The syntax for more complicated C types is often counter-intuitive, especially in cases of multiple levels of functions and arrays.
The ever-useful cdecl.org website supports blocks: declare f2b as block(pointer to function(int, pointer to pointer to char) returning int) returning block(int, pointer to pointer to char) returning int (they say "block" whereas I say "pointer to block")
Your block definition written out using full block literal syntax (including return types) would be something like this (remembering to copy the block in order to return it):
int (^(^f2b)(int (*) (int, char **)))(int, char **) =
^int (^(int (*func)(int, char **)))(int, char **) {
return Block_copy(^int (int argc, char **argv) {
return func(argc, argv);
});
};
Return types may be omitted in block literals, so it could be written like:
int (^(^f2b)(int (*) (int, char **)))(int, char **) =
^(int (*func)(int, char **)) {
return Block_copy(^(int argc, char **argv) {
return func(argc, argv);
});
};

adding heterogeneous members to an array

I am playing with a custom threads api, i want to spawn a new thread with two pointers to message channels and an integer.
spawn_thread(Proctype Procedure, int argc, char *argv[]);
I am using 'channels' as an shared area between threads.
i have three variables:
`Chan *return, Chan *receive and an int n'
Could i simply cast all of the values i want to store in *argv[], to chars?
The reason i haven't done this is the width of the char is only 8 bits so a max value of 255, which isn't enough to hold pointer or large values.
One common approach to storing heterogeneous data in a C array is with tagged unions:
typedef enum {chDataReturn, chDataReceive, chDataInt} ChannelDataType;
struct ChannelData {
ChannelDataType type;
union {
ChanReturn ret;
ChanReceive rcv;
int num;
} data;
};
Now your spawn_thread prototype would look as follows:
spawn_thread(Proctype Procedure, int argc, struct ChannelData *argv);
Users would put the data into the array of argvs, "tagging" each item with its type, like this:
struct ChannelData *data = malloc(3*sizeof(struct ChannelData));
data[0].type = chDataReturn;
data[0].data.ret = myReturn;
data[1].type = chDataReceive;
data[1].data.ret = myReceive;
data[2].type = chDataInt;
data[3].data.num = 12345;
spawn_thread(myProc, 3, data);
// Wait for the thread to finish, and then...
...
free(data);
char * argv[] passes a char ** which you can just as easily cast to a void ** essentially allowing you to pass an array of void * to whatever you like.
char * argv[] = {&return, &receive, &n};
spawn_thread(Procedure, 3, argv);
Procedure(int argc, char *argv[]) {
char return = *argv[0];
char receive = *argv[1];
int return = *(int *)argv[2];
// ...
}

multiple input parameters from command line in C

I am trying to pass multiple parameters when running a compiled C code
code would be like this
void main(char argc,char *argv[]){
printf("%s",argv[1]) //filename
FILE *file = fopen(argv[1], "r")
printf("%s",argv[2]) //function to be called
char* func_name = argv[2];
printf("%s",argv[3]) //how many times the function is called
int repeat = argv[3];
for(int i=0;i<repeat;i++){
func_name(file) //calls some function and passes the file to it
}
}
i would compile like this
gcc cprog.c -o cprog
run like -
./cprog textfile.txt function1 4
how do i do this ? any help would be appreciated !
First off:
You are missing some semicolons, so your code won't even compile.
argv[] are strings, so you'll have to convert them to integers if you want to use them as such.
C does not store function names in the binary, so you have to create some kind of calling table.
Below find a working example. I creates a struct that maps a name to a function, implement that function and go look for it. It's quite buggy (no input validation is done), but gives you a proof of concept on how to possibly implement this.
#include <stdlib.h>
#include <stdio.h>
struct fcn_entry {
char *name;
void (*fcn)(char *);
};
void fcn1(char *fn) {
printf("fcn1: %s\n", fn);
}
void fcn2(char *fn) {
printf("fcn2: %s\n", fn);
}
void main(char argc,char *argv[]){
// name-to-function table
struct fcn_entry entries[] = {
{ "fcn1", fcn1 },
{ "fcn2", fcn2 },
{ NULL, NULL }
};
void (*fcn_to_call)(char *);
int i = 0;
printf("%s",argv[1]); //filename
printf("%s",argv[2]); //function to be called
char* func_name = argv[2];
i = 0;
while(entries[i].name != NULL) {
if (strcmp(entries[i].name, func_name) == 0) {
fcn_to_call = entries[i].fcn;
break;
} else {
fcn_to_call = NULL;
}
i++;
}
printf("%s",argv[3]); //how many times the function is called
int repeat = atoi(argv[3]);
for(i=0;i<repeat;i++){
fcn_to_call(argv[1]);
}
}
There are a lots of error here.
int repeat = argv[3]; //You must convert char* to int before assignment.
func_name(file) //func_name is a char* not a function. C does not support reflection so there is no way to call function like this.
To be able to call a function that you have as a string, you have know which name is paired to which function.
If all functions take the same arguments, you can have an array of structures with name and function pointer, and then match the name with the correct entry in the table.
Otherwise, if the arguments are different you have to have a chain of strcmp calls to call the correct function.

Resources