当前位置:   article > 正文

C调用C++和C++调用C_c语言调用c++

c语言调用c++

1.C调用C++

若C调用的是C++全部函数的代码

  • 将函数用extern "C"声明;;
    然后C代码中不要include C++的头文件, 而采用直接在C中增加函数声明的方式;
  • C调用C++,使用extern "C"则是告诉编译器依照C的方式来编译封装接口,当然接口函数里面的C++语法还是按C++方式编译

方法1(需要改动以前的C++代码):

C++代码
/*C++ code*/
extern "C" void f(int);
void f(int i)
{
// your code
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
C语言代码
void f(int);  // 不引入, 而只是直接声明
void cc(int i)
{
	f(i);  //调用
	// other code
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

若C调用的是C++成员函数的代码

  • 如果想要调用C++类中的成员函数, 由于C中没有类, 因此需要一个包装函数来调用这个成员函数, 并返回结果;
  • 如果你想要在C里调用成员函数(包括虚函数),则需要提供一个简单的包装(wrapper)
    方法2(需改动以前的C++代码):
// C++ code:
class C
{
// ...
virtual double f(int);
};

extern "C" double call_C_f(C* p, int i) // wrapper function
{
	return p->f(i);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
/* C code: 调用C::f()*/
double call_C_f(struct C* p, int i);
void ccc(struct C* p, int i)
{
	double d = call_C_f(p,i);
	/* ... */
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

方法3(不改动以前的C++代码):

  • C代码.c只能调用C的函数,所以可以用包裹函数去包裹C++函数,然后把这个包裹函数以C的规则进行编译,这样C就可以调用这个包裹函数了
C++代码
CppAdd.h
int cppadd(int x, int y);

CppAdd.cpp
#include "CppAdd.h"
#include <stdio.h>

int cppadd(int x, int y) {
    printf("from C++ function.\n");
    return (x + y);
}

编译静态库 libCppAdd.a
g++ -c CppAdd.cpp
ar -r libCppAdd.a CppAdd.o
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
C++代码(包裹函数)
CppAddWrapper.h
#ifdef __cplusplus
extern "C" {
#endif

int cppaddwrapper(int x, int y);

#ifdef __cplusplus
}
#endif

CppAddWrapper.cpp
#include "CppAddWrapper.h"
#include <stdio.h>
#include "CppAdd.h"

int cppaddwrapper(int x, int y) {
    printf("from wrapper.\n");
    int sum = cppadd(x, y);
    return sum;
}

编译wrapper静态库 libCppAddWrapper.a
g++ -c CppAddWrapper.cpp
ar -r libCppAddWrapper.a CppAddWrapper.o
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
C代码
main.c
#include "CppAddWrapper.h"
#include <stdio.h>

int main()
{
  int sum = cppaddwrapper(1, 2);
  printf("1+2 = %d\n", sum);
  return 0;
}

编译main,同时指定libCppAdd.a 和 libCppAddWrapper.a
gcc -o main main.c -L. -lCppAddWrapper -lCppAdd
或者把libCppAdd.a合并到libCppAddWrapper.a中
ar -x libCppAdd.a         # 提取CppAdd.o
ar -x libCppAddWrapper.a  # 提取CppAddWrapper.o
ar -r libCppAddWrapper.a CppAdd.o CppAddWrapper.o # 打包libCppAddWrapper.a
gcc -o main main.c -L. -lCppAddWrapper  # 只需要连接libCppAddWrapper.a即可
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

2.C++调用C

方法1:

  • 在include的时候,要采用extern “C” 代码块形式.
  • 为什么使用extern “C”?因为cpp支持了函数重载,在编译生成的汇编代码中,会对函数名字进行命名改编,并不是C语言中的简单的函数名而已。
C++代码
// add.h整个头文件中的所有函数都是分布在多个xxx.c文件中的, 因此肯定xxx.obj是按照Ccompiler规则编译, 函数名无改动,
 
// 那么, C++中引用头文件的时候, 要在外部加上extern "C"包裹, 表示说我知道这部分是
//采用Ccompiler规则的函数名, 我会采用这个规则去找函数;

#include <iostream>
extern "C" {
    #include "add.h"  // 由add.h和add.c组成
}
using namespace std;

int main() {
    cout << addTwoNumber(10, 20) << endl;
    system("pause");
    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

方法2:

// C Code
void foo( int x );
  • 1
  • 2
C++这样调用C函数
// C++ Code
extern "C" void foo( int x );
  • 1
  • 2
  • 3

方法3:

C语言代码
CAdd.h
int cadd(int x, int y);

CAdd.c
#include "CAdd.h"
#include <stdio.h>

int cadd(int x, int y) {
    printf("from C function.\n");
    return (x + y);
}

编译libCAdd.a
gcc -c CAdd.c           # 生成CAdd.o
ar -r libCAdd.a CAdd.o  # 归档生成libCAdd.a

编译动态库 libCAdd.so
gcc -shared -o libCAdd.so CAdd.c
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
C++代码
#include <stdio.h>

extern "C" {
#include "CAdd.h"
}

int main()
{
  int sum = cadd(1, 2);
  printf("1+2 = %d\n", sum);
  return 0;
}

编译main
-l指定库名称,优先链接so动态库,没有动态库再链接.a静态库。
g++ -o cppmain cppmain.cpp -L. -lCAdd
若找不到动态库的搜索路径,则:export LD_LIBRARY_PATH=./设置当前路径为系统链接库目录就可以了
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

方法4:

  • 无论C还是C++直接正常include就可以使用了
#ifdef __cplusplus
extern "C" {
#endif

int cadd(int x, int y);

#ifdef __cplusplus
}
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

其他说明:

  • 时常在cpp的代码之中看到这样的代码: 特别是C ++中引入C的头文件,这些C头文件中出现很多如下代码
  • 其中__cplusplus是C++编译器的保留宏定义.就是说C++编译器认为这个宏已经定义了
  • extern "C"是告诉C++编译器,连接的话按照C的命名规则去找
#ifdef __cplusplus extern "C" 
{ 
#endif

//一段代码

#ifdef __cplusplus
}
#endif  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/194914
推荐阅读
相关标签
  

闽ICP备14008679号