How does C + + call the C interface?

Time:2021-11-28

✨ Sometimes, when I want to call the C interface in c++ code, I compile and report it wrong!!!

elicit questions

You may wonder, isn’t C + + compatible with C? Just call it directly? Why is this the case? Imagine that some interfaces are implemented in C and provide libraries, so how to use them in C + +?

Let’s not make any distinction and see what unexpected things will happen under ordinary circumstances. First, provide a C interface:

//test.c
#include"test.h"
void testCfun()
{
    printf("I am c fun\n");
    return;
}

Here we compile it into a C object file:

gcc -c test.c

In addition, a header file test. H is provided:

#include<stdio.h>
void testCfun();

Our c + + code calls are as follows:

//main.cpp
#include"test.h"
#include<iostream>
using namespace std;
int main(void)
{
    /*Call C interface*/
    cout<<"start to call c function"<<endl;
    testCfun();
    cout<<"end to call c function"<<endl;
    return 0;
}

compile:

$ g++ -o main main.cpp test.o
/tmp/ccmwVJqM.o: In function `main':
main.cpp:(.text+0x21): undefined reference to `testCfun()'
collect2: error: ld returned 1 exit status

Unfortunately, the last link reported an error, saying that testfun could not be found, but we did define this function. Why can’t you find it?

Uncover the fog

As we all know, functions in C + + support overloading, but C does not. In order to support function overloading, C + + cannot “generate” function symbol information only through the function name, because the function names of overloaded functions are the same, so it also determines the unique function signature according to the input parameters, namespace and other information.

OrThe method of generating function signature in C + + is inconsistent with that in CTherefore, even if the function names are the same, the final function signatures of C and C + + are still different. Of course, here is another matter. We won’t go into detail. Let’s look at the difference between the function symbols in the two files:

$ nm test.o|grep testCfun
0000000000000000 T testCfun
$ nm main.o|grep testCfun
                U _Z8testCfunv

So it’s strange that they can be linked together! How to link if the names are different?

resolvent

So how to deal with it? Obviously, we must tell the linker that this is a C interface, not a C + + interface, so we need to add extern C. we modify test. H

#include<stdio.h>
extern "C"{
void testCfun();
}

Here, wrap the testfun interface with extern “C” and tell the compiler that this is the C interface. Ha, you should handle it in the way of C code. Recompile:

$ g++ -o main main.cpp test.o
$ ./main
start to call c function
I am c fun
end to call c function

optimization

Although the above C interface can be called normally by C + +, what if the C interface is to be called by C code? Add main. C as follows:

//main.c
#include"test.h"
int main(void)
{
    /*Call C interface*/
    testCfun();
    return 0;
}

compile:

$ gcc -o main main.c test.c
In file included from main.c:2:0:
test.h:2:8: error: expected identifier or '(' before string constant
 extern "C"{
        ^
In file included from test.c:2:0:
test.h:2:8: error: expected identifier or '(' before string constant
 extern "C"{

No accident, it’s wrong again. Obviously,There is no such way of writing extern “C” in C languageTherefore, in order to enable test. C code to be called by both C + + and C, it needs to be rewritten as follows:

#include<stdio.h>
#ifdef __cplusplus
extern "C"{
#endif

void testCfun();

#ifdef __cplusplus
}
#endif

Here through__ Cplusplus macro is used to control whether external “C” is required. If it is a C + + compiler, the external “C” part will be preprocessed, so that the test. C code can be used for both C + + and C.

Why can we directly call some standard C library functions in C + + code? Even if you call functions such as printf in the main function, there will be no link errors. Because the library function already has similar processing.

summary

C + + supports overloading, but C does not. C + + cannot directly call the interface written by C code. Therefore, if your C code wants to be called by C and also wants to be called by C + +, don’t forget extern “C”.

Remember, when C code is called by C + +, it needs to be usedextern "C"Enclose the declaration of the called function.

Follow & & contact

gitee: https://gitee.com/cmcc-oneos/OneOS-Lite

docs: https://oneos-lite.com/

Quoted from:https://gitee.com/cmcc-oneos/OneOS-Lite/blob/dev/docs/quick_guide/cplusplus/c++-call-c.md