简体   繁体   中英

Passing function pointers & int references to another function

Just started working on ac project. Need help with passing function pointers/macro functions/etc. I'm a php & python OO guy, but new to c. I tried to generalize the example for this post. I have a main.c with a lib for the Axon microcontroller I'm working with. Works like a charm with everything in main.c. I need to move some of the functionality out of main to more organized lib files as my code grows. The base microcontroller lib creates a macro function that allows me to send data to the microcontroller to make a servo move left or right. I now need to create a servo specific file (HS-422.c) that will will allow me to pass references/pointers(?) to a generic function that will execute for each servo to ease on code duplication.

Keep in mind I'm only focused on passing macros/functions/variable references to other functions and have them called / set. The other basics of c I understand. I must have tried a 100 different ways to make this work today with no luck. So just wrote a simplified version hoping you might get an idea of what I'm attempting.

Thank you for your help!

/*
 * main.h 
 * I'm trying to make a pointer or reference to the macro.  
 * The original file had:
 * #define servo1(position) servo(PORTE,2,position); 
 */

 // servo is a macro defined in another microcontroller file
 #define (void)(*servo1)(position) servo(PORTE,2,position); 
 #define (void)(*servo2)(position) servo(PORTE,3,position); 


/* main.c */

// init main functions
void servo_scan(void);

// init vars
int servo1_location = 0;
int servo2_location = 0;

int main(void)
{
  for(;;)
  {
     servo_turn();
  }
}

// get the servos to turn
void servo_turn(void)
{
  turn_servo( *servo1, &servo1_location, 200);
  turn_servo( *servo2, &servo2_location, 950);
}


/* HS-422.c */
void turn_servo(void (*servo)(int position), int &currentLocation, int newLocation)
{
  // turning
  for(uint16_t  i=&currentLocation; i<newLocation; i=i+10)
  {
    // turn servo
    // hoping the specifc passed servo# pointer gets called
    *servo(i);     

    // set value by reference to origional servo#_location var. making sure.
    &currentLocation = i; 

    // pause
    delay_ms(20);
  }
}

It's not really clear to me exactly what you're trying to achieve, but what is clear is that you don't really understand the concept of pointers/references in C - so I'll try to clarify, and hopefully that will help you implement what you need.

Firstly, there is no such thing as a "reference" in C. The only alternative to passing by value is to pass a pointer. A pointer is basically just a memory address, and you can get a pointer (memory address) to a variable using the & (address of) operator. When passing a pointer variable to a function, you do something like the following:

Given a function which takes a pointer:

int foo(int* pointer);

You would pass the memory address of an int variable to this function like so:

int x = 10;
foo(&x);

So right off the bat, you can see that your function definition above is wrong:

void turn_servo(void (*servo)(int position), int &currentLocation, int newLocation);

This is simply a syntax error. It will not compile because of the int &currentLocation. The & operator is used to take the address of a variable. It can't be used in a function parameter. If you want a "reference" to currentLocation , you need to pass in a pointer, so your function parameters should be written as:

void turn_servo(void (*servo)(int position), int* currentLocation, int newLocation);

Secondly, when you want to modify the value pointed to by the currentLocation pointer, you need to use the * operator to dereference the pointer. So, the line where you set currentLocation is not correct. What you want to say is:

// set value by to origional servo#_location var. making sure.
*currentLocation = i; 

And of course, the line:

  for(uint16_t i=&currentLocation; i<newLocation; i=i+10)

should be:

  for(uint16_t i= *currentLocation; i<newLocation; i=i+10)

Note that in your original code you use the & operator in both cases, which takes the address of a variable. Since currentLocation is already a memory address, this would result in taking the address of an address , also known as a pointer-to-a-pointer, which is certainly not what you want here.

Finally, the phrase "pointer or reference to the macro" is completely nonsensical. A macro is not a function. It is more like a meta-function: essentially it is a template used by the C preprocessor to generate further source code. The C preprocessor is invoked before the compilation phase, and basically acts as a find/replace mechanism in the source code. You can't have a pointer to a macro, because for all intents and purposes macros don't even exist in the compilation phase. They are only meaningful to the preprocessor.

There may be more here, but ultimately you seem to have a fundamental misunderstanding of pointers (as well as macros) in C, and short of providing a complete tutorial, the best I can do is point out the syntax problems. I highly recommend you read a good introductory book to C , which will certainly go over pointers, macros, and functions.

I have picked the main point of your code and have this code below.
You may want to modify your #define in your original code.
Please see the code below: (you can also run this)

void myFunc(int pos);
void myFunc2(int pos);

int main (int argc, const char * argv[]) {


    typedef void (*pFunc)(int);
    pFunc pfArr[2];
    pfArr[0] = &myFunc;
    pfArr[1] = &myFunc2;


    int x = 3;
    int newLoc = 4;
    turn_servo(pfArr[1], x, newLoc);
    turn_servo(pfArr[0], x, newLoc);


    return 0;
}



void turn_servo(void (*servo)(int position), int currentLocation, int newLocation)
{
    printf("\nturn_servo starts");
    printf("\nturn_servo currentLocation: %d", currentLocation);
    printf("\nturn_servo newLocation: %d", newLocation);
    servo(1);

}

void myFunc(int pos)
{
    printf("\nmyFunc starts");
    printf("\nmyFunc pos: %d", pos);
}

void myFunc2(int pos)
{
    printf("\nmyFunc2 starts");
    printf("\nmyFunc2 pos: %d", pos);
}

Your turn_servo() function will now accept two functions as parameter (either myFunc() or myFunc2()).
Just get the main point of this code and apply it. Hope this will help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM