Calling Serial.read() and Serial.write() from .c

Hey,

I only know C, but not C++. So far my arduino projects have been a C/C++ mix of files.

I've found I can call C functions from C++ fine, by using the following in the .pde file:

extern "C" {
void C_function_prototype1(void);
// ...

But now I'd like to do the converse, call C++, and more specifically the Serial.read and Serial.write functions to read and write one byte at a time, from C.

I found the following method in two different FAQs:
http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html#faq-32.6

So in my .pde file I have:

extern "C" {
    void test(void);
    void wtf(void);
}

void wtf(void)
{
    return;
}

Which errors on compile with:

error: previous declaration of 'void wtf()' with 'C++' linkage

So, what do I do now? :frowning:

I just have to ask:
Why not simply use C++ and call the Serial object directly? ::slight_smile:

Enlighten me please :slight_smile:

Well, I only know C, I like C. Matter of preference mostly.

So write in C! :slight_smile:

C is a subset of C++. Don't like classes? Don't use them.

Basically, you don't have to "do" anything. Just write your code in C, and call C++ classes only when necessary.

Well, that would be all good and fine if C were a subset of C++.

But it's not.

Take the following trivial piece of code, which is valid C but invalid C++:

char *new = malloc(10);

Avoiding the small number of extra reserved words is a small price to pay compared to the pain of trying to call the future from the past.

Sure, but changing the variable name doesn't fix that line :wink:

OK...I give up...missing a cast to (char *)? You should be doing that anyways in C else you're abusing the language.

Well, it's only missing from a C++ perspective, but indeed C has implicit casting to/from void*.

It however is not "abusing the language". I think most sane C programmers consider casting malloc bad, I can think of 2 reasons:

  • It's pointless
  • It can hide a bug

I don't see any benefits, and one downside. Thus, overall it is to be avoided in C.

I completely disagree.

Casting malloc is good programming practice because it documents the programmer's intention and can catch mismatches between the expected type and the actual type.

IMO anything explicit is better than implicit, and as you said "C has implicit casting to/from void*", which, still IMO, is abusing the language.

Casting malloc is good programming practice

We officially disagree... Casting forces conversion whether the source is appropriate or not.

OTOH, having to cast malloc() (or provide macros/inline allocator functions) seems a small price to pay to avoid the complications of mixing C and C++ in microcontroller class applications, especially since malloc() is usually to be avoided anyway. IMO.

We officially disagree... Casting forces conversion whether the source is appropriate or not.

....except when the source is "void *" which is basically saying "I DON'T KNOW WHAT TYPE I AM POINTING TO!!! CAST ME!!!"

Weeeeeeee.

I believe I've made significant head way in solving my problem. The outlined extern while causing an error in my .pde file, works fine in a seperate .cpp file (for reasons beyond my few days of arduinoing experience).

I suspect the issue is that the IDE automatically generates function prototypes for your functions in the .pde file, thus disagreeing duplication thus error.

C is a subset of C++.

Not quite.

C++ is a superset of C.

-j

If A is a superset of B, then B is a subset of A.

If one is true, the other is also true. In this C/C++ case, they're both wrong.