Hyz Yuzhou
Hyz Yuzhou

Reputation: 83

how to use c and c++ together

There is a example I find:

in main.c

int main() {
     cppsayhello("Hello from C to C++");
     return 0;
}

in cppsayhello.cpp

#include<iostream>
#include"cppsayhello.h"

extern "C" void cppsayhello(char* str);

void cppsayhello(char *str) {
    std::cout << str << std::endl;
}

It works! main.c includes nothing so how can main.c know of the existence of the function cppsayhello? Would somebody tell me how it works behind the scenes.

(I'm now working on an embeded system. The bottom-level is written in C, and I want to use c++ to construct top-level application. But It's hard to work with 2 language.)

Upvotes: 1

Views: 290

Answers (3)

vlad_tepesch
vlad_tepesch

Reputation: 6925

The whole thing is undefined behavior and works by luck. A few things happen behind the scenes but your compiler should complain a lot.

  1. in your main.c: in C a function the compiler does not know is implicitly expected to be of return type int without checking the parameters. (this applies to C older than C99. C99 or later will give you an error with this code)
  2. in your cppsayhello.cpp: thanks to the extern "C" your C++ compiler creates an object file that contains a function with C calling conventions, without name mangeling.
  3. the linker took both objects and finds in cppsayhello.obj a exportet symbol cppsayhello and in main.c a required symbol cppsayhello. so it links the two.

obviously they have different signatures but in your case the returned value is ignored and the parameters are compatible. But the actual runtime behavior may depend on architecture and compiler.

In Short: Your example is very bad code.

Upvotes: 0

Peter
Peter

Reputation: 36627

It is a sign that your C compiler predates the 1999 standard, since later C compilers will reject that main() function.

Generally speaking, with older C compilers, your C code will link even when the usage of an implicitly declared function does not match the actual definition. The result is undefined behaviour (although, in practice, the code often still works - one possible manifestation of undefined behaviour is that the code works as expected with at least some compilers).

It works behind the scenes because C - unlike C++ - does not support function overloading. So any function named cppsayhello() will be given the same name (in the object file) by the compiler, so the linker can match things up. So you could define your cppsayhello() to have any return type, and any set of arguments, you desire - your code will still compile and link. However, the linker must only see one definition (it will complain about a multiply defined symbol if it encounters more than one definition of anything - for example, linking two object files that each contain a definition of some function).

Your code would avoid the undefined behaviour if the main() function had visibility of a proper declaration of the function.

void cppsayhello(const char *);

int main()
{
     cppsayhello("Hello from C to C++");
     return 0;
}

That will prevent the main() function compiling if it uses the function in any manner inconsistent with the declaration.

Upvotes: 1

Zaboj Campula
Zaboj Campula

Reputation: 3360

The main.c is compiled by a C compiler that allows implicit function declaration. When C compiler finds a function that is not declare yet it assumes it is int function() which means function with any number of any parameters in C.

C99 and newer does not allow implicit declaration and the code would not compile with C99 compliant compiler.

Upvotes: 2

Related Questions