"undefined reference to" ...a function i

Sigh. I know there have been a lot of questions @ .h, .c, and .cpp files. I've read through the forum threads and also the description of the build process but I'm still struggling here. (I've tried lots of different things but nothing has worked).

Here's the set up: -I want to use some open source c code. -I have the code within my sketch folder and the .c and .h files show up as tabs. -I have #includes (#include "line.h" - relative path) for each of the .h files at the top of my sketch -My sketch compiles ok.

The problem is that I can not call any of the functions in the .c files without getting the "undefined reference" error. This occurs even if the function is declared in the .h file for corresponding .c file. Simply making the call below throws the error and prevents compilation

Is there some silver bullet here? The c code I am using compiles fine - I just can't reference it from my sketch. How do I open line of communication between my sketch and this #included code?

Thanks for any tips!

void loop(){
 plotter_init();
}

The error msg:

CONVERSION_05_MEGA.cpp.o: In function loop': CONVERSION_05_MEGA.cpp:37: undefined reference toplotter_init()'

C++, which the Arduino is programmed in, performs name-mangling. C, which your external functions are written in, does not.

Name-mangling means that the actual function that gets called is called using a name that is composed of the class name, function name, and argument type names.

In order to call a C function from a C++ function, the compiler needs to know that it should use C calling syntax, not C++ calling syntax.

In the header file, before any function declarations, add:

#ifdef __cplusplus
 extern "C" {
#endif

After all function declarations, add:

#ifdef __cplusplus
}
#endif

This will allow the C functions to be called from C++.

YAY! That seems to work (error went away).

Are there any issues I should be aware of passing paramsfrom sketch > .c functions or returning values from .c function > sketch?

Thanks for taking the time!

Are there any issues I should be aware of passing params from sketch > .c functions or returning values from .c function > sketch?

There is no difference between passing arguments to C functions and passing arguments to C++ functions.

I also found that in order to call functions in my sketch from the .c code I had to declare the function as "extern "C"" in the sketch - I've done that before - but didn't know @ the header declaration you posted. Looks like I have two-way communication happening now - so I can get back on track.

thanks!

extern "C"{
  void callSketch(int x){
   val2 += x;
   Serial.println(val2);
  }
}
extern "C"[glow]{[/glow]
  void callSketch(int x){
   val2 += x;
   Serial.println(val2);
  }
[glow]}[/glow]

The highlighted braces are not required in this case. They are needed if you intend to declare multiple functions that can be called from C code, but it's still better to explicitly indicate that for each function.

extern "C" void callSketch(int x)
{
   val2 += x;
   Serial.println(val2);
 }

Not using the block declaration method results in errors:

extern "C" byte getPenStatus(){
  return pen_status; 
}

Error msg: previous declaration of ‘byte getPenStatus()’ with ‘C++’ linkage

CONVERSION_06_MEGA.cpp: In function ‘byte getPenStatus()’:
CONVERSION_06_MEGA:21: error: previous declaration of ‘byte getPenStatus()’ with ‘C++’ linkage
CONVERSION_06_MEGA:74: error: conflicts with new declaration with ‘C’ linkage

The block method seems to work though so :slight_smile:

I suspect that this is an Arduino IDE problem, not a C/C++ problem. The Arduino build pre-processes sketches and adds (C++) function prototypes. Since the compiler sees the auto-generated prototype first, your function definition causes a conflict.

My theory as to why the block declaration method works is that it fools the Arduino preprocessor, which doesn't recognize it as a function definition, and so does not generate a function prototype.

Someone less lazy than me could verify this by looking at the generated source code. :)

Regards,

-Mike