http://fangzhzh.info/blog/mixing-c-and-cpp-programming.html

在最近的arm开发中,因为一些特定的需求,需要使用从C文件中调用以前C++程序中的类和方法。参考网上的一些资料,本文1将相关的知识点简要总结如下:c&c++混合编程的注意事项,在c++函数中调用c函数的方法,在c函数中调用c++函数的方法,在c函数中调用C++对象及其中数据的方法。并在本文的末尾给出C和C++混合编程的例子,例子分别以Makefile和VC6.0工程的形式展现。

注意事项

本部分是从较高的角度需要注意的问题:

  • C和C++编译器必须要兼容
  • C和C++编译器要有兼容的头文件和运行库

建议使用同一个供货商的编译器:即如果使用的gnu,那么C编译器是gcc,C++编译器是g++。

如何在C++代码中包含标准C头文件?

包含一个标准的头文件(如<cstdio>),不需要任何特别的处理。

// c++ 代码
#include <cstdio>               // 头文件包含没啥特别处理
int main()
{std::printf("Hello world\n");// 函数调用没啥特别处理
  return 0;
}

如果,你认为std::printf中的std::很奇怪,那么最好的方式就是“习惯它”。换句话说,这是使用标准库函数的标准方法,所以习惯这种用法就好了。

但是,如果你想要使用C++编译器来编译C代码的话,就不用使用这么奇怪的std::printf()了。这种情况下,你需要包含<stdio.h>,而不是<cstdio>,神奇的命名空间会替你解决所有事情。代码如下:

//使用C++编译器编译的C代码
#include <stdio.h>               // 头文件包含没啥特别处理
int main()
{printf("Hello world\n");// 函数调用没啥特别处理
  return 0;
}

补充:如果使用非标准库的头文件的话,关注点会有所改变,非标准库的使用有以下两种情况:不能修改头文件和能够修改头文件。

如何在C++代码中包含非系统C头文件?

如果在C++系统中使用一个非系统提供的c头文件时,需要将#include代码用extern “C”{}包含起来,这个声明告诉C++编译器,包含在内的是C函数的头文件。

//C++ 代码

extern "C" {
//get declaration for f(int i, char c, float x)
  #include "my-c-code.h"
}int main()
{f(7, 'x', 3.14);   //正常调用
}

补充:可能出现的不同情况系统提供的标准头文件(比如<cstdio>)和能够修改头文件。

如何修改C头文件,以使之方便的被C++代码#incldue?

如果需要包含一个非系统的C头文件,同时,你拥有修改此文件的权限,那么强烈建议在文件的内部加上extern “C” {…},以使用C++程序员能够方便的使用。当然,作为C编译器,是不理解什么叫extern “C”的,因此,需要将extern “C”使用#ifdef包起来。

  • 第一步:在C头文件的最顶端加上如下代码(__cplusplus只存在于C++编译器下)
#ifdef __cplusplus
extern "C" {
#endif
  • 第二步:在C头文件的最尾部加入如下代码
#ifdef __cplusplus
}
#endif
  • 现在,就可以在C++代码中使用C头文件,而不用使用任何蹩脚的extern “C” {}
// this is c++ code
//get the declaration of f(int i, char c, float x)
#include "my-c-mode.h"
int main()
{f(7, 'x', 3.14);   //正常调用
}

补充:可能出现的不同情况系统提供的标准头文件(比如<cstdio>)和不能修改头文件。

如何在C++代码中调用非标准的C函数?

现在也许你有一个单独的C函数,但是呢,出于某种原因,你并想包含声明此函数的头文件。那么你可以在C++代码中声明此单独的函数,代用extern “C” 的语法。你应该如下方式使用:

extern "C" void  f(int i, char c, float x);

如果是许多程序的话,可以用大括号包含:

extern "C" {
void   f(int i, char c, float x);
int    g(char* s, char const* s2);
double sqrtOfSumOfSquares(double a, double b);}

经此声明,在C++函数中调用这些C函数就变的很简单:

int main()
{f(7, 'x', 3.14);   // Note: nothing unusual in the call
}

如何写出能够被C代码中调用的C++函数?

当知道一个C++函数会被C编译器调用时,可以使用extern “C” 结构来声明函数。

//c++ code
//声明
extern "C" f(int, char, float);//....

//在某个C++模块中定义此函数
void f(int i, char c, float x)
{
//.....
}

extern “C” 这行告诉C++编译器,当有external信息在链接时,使用C调用规范和函数命名方式。

另:因为C并不支持重载,所以不能够实现用C调用重载函数。

C/C++混合编程时,出现linker错误

如果,函数没有正确的设置了extern “C”,那么有可能出现链接错误而不是编译错误。这是因为C++编译器经常会”mangle”函数名(做特殊处理)– 一种于C编译器不同的方式。

如何将一个C++类的对象传给一个C函数?

例子: Fred.h:

//此头文件C/C++编译器都访问
/* This header can be read by both C and C++ compilers */
 #ifndef FRED_H
 #define FRED_H #ifdef __cplusplusclass Fred {public:Fred();void wilma(int);private:int a_;};
 #elsetypedefstruct FredFred;
 #endif #ifdef __cplusplusextern "C" {
 #endif #if defined(__STDC__) || defined(__cplusplus)extern void c_function(Fred*);   /* ANSI C prototypes */extern Fred* cplusplus_callback_function(Fred*);
 #elseextern void c_function();        /* K&R style */extern Fred* cplusplus_callback_function();
 #endif #ifdef __cplusplus}
 #endif #endif /*FRED_H*/

Fred.cpp:

// This is C++ code

#include "Fred.h"int main()
{Fred fred;c_function(&fred);...
}

c-function.c

/* This is C code */#include "Fred.h"void c_function(Fred* fred)
{cplusplus_callback_function(fred);
}

c代码不能像c++代码一样,能够分辨出两个指针指向的是同一个对象,除非两个指针是严格的同一个类型。

举个例子,假设有两个对象,Derived* dp,和Base* bp,下面语句if(dp == bp)在c++下正常,c++编译器会自动将两个指针转为同一个类型,在这个例子中,两个指针都给转换成Base*,然后比较。这个过程,C做不到。

显而易见:C编译器不知道如何做种指针转换,所以如果非要对比这两个指针的话,Derived*到Base*的转换应该在C++编译器的地方完成,而不要C编译器做做这个工作。

C函数能够直接访问C++类的数据吗?

看情况。

在以下情况下,C函数能够直接访问C++对象的数据成员:

  • 没有虚函数(也不能用继承的虚函数)
  • 所以的数据在同一个访问层次(private/protected/public)
  • 不包含有虚函数的子对象如果C++类有任意基类(或者是包含基类的子对象),直接认为data在技术上来说,都是不可移植的,因为继承层次下的类的数据的布局不是硬性规定的,所以每个编译器可能会有所不同。想深入了解虚函数相关的实现技术可参考<深入探索C++对象模型>2

链接程序+例子

展示本文用法的例子及使用linux时的链接方法,本例子有Makefile和VC6.0工程两种组织方式:下载地址。

Time-stamp: 2010-12-22 21:48:49 fangzhzh

Footnotes:

1 http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html, http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html

2 http://book.douban.com/subject/1091086/

C 和 C++ 混合编程相关推荐

  1. matlab两个多项式相除,C++和MATLAB混合编程求解多项式系数(矩阵相除)

    摘要:MATLAB对于矩阵处理是非常高效的,而C++对于矩阵操作是非常麻烦的,因而可以采用C++与MATLAB混合编程求解矩阵问题. 主要思路就是,在MATLAB中编写函数脚本并使用C++编译为dll ...

  2. C和C++混合编程的Makefile的编写!

    在项目实践中,经常遇到C和C++混合编程的情况. 目前的业务需求是: c写的几个文件,和一个C++文件要整合为一个动态库,被C++调用.而这个动态库的生成过程中,会链接几个基础的开发库,比如libz, ...

  3. 怎样用matlab打开mw文,C# matlab混合编程 MWArray使用笔记

    C# matlab混合编程 徐凯Email:xukai19871105@http://www.doczj.com/doc/1a6e191fff00bed5b9f31dbf.html 这几天突然想搞一搞 ...

  4. matlab2014a + win764bit + vs2013混合编程(.m转成dll供C++调用)

    在matlab中可以通过mbuild工具将.m文件编译成dll文件供外部的C++程序调用,这样就可以实现matlab和C++混合编程的目的. 1. 使用matlab生成dll文件 1.1 首先需要带有 ...

  5. .Net(c#) 通过 Fortran 动态链接库,实现混合编程

    c# 与 Fortran 混合编程解决方案主要有两种: 1. 进程级的交互:在 Fortran 中编译为控制台程序,.Net 调用(System.Diagnostics.Process),然后使用 P ...

  6. c 与matlab混编,谈谈Matlab与C/C++或C#的互调用(混合编程)

    记得当初一个师姐问我知不知道如何在Matlab里调用C++的程序,还真把我问住了.因为我以前就知道C++调用Matlab的方法,这方面网上资料一大堆.没想到现在自己突发奇想又遇到另外一个问题,Matl ...

  7. Linux C++与Python混合编程(g++生成链接库与python调用)

    gcc/g++ 链接库的编译与链接 这一篇对动态链接库和静态链接库以及编译结果讲得很清楚,目前看到最好的. Linux下Python与C++混合编程

  8. 基于引擎的matlab+vc混合编程的配置

    前段时间在项目中做了一些关于基于引擎的vc+matlab混合编程的工作. 如果你是混合编程新手,我相信使用引擎的方式编程是比较简单快捷的一种方式. 当然这种方法也有其缺点,就是不能脱离matlab运行 ...

  9. 开题:在移动开发中使用JavaScript进行混合编程提高代码复用率

    2019独角兽企业重金招聘Python工程师标准>>> 问题 通常开发一个移动应用,因为存在iOS和Android两种操作系统,因此所有代码都要使用两种语言编写两遍,因此几乎所有开发 ...

  10. c 使用matlab引擎,[转载]C与MATLAB混合编程之调用MATLAB引擎

    Visual Studio调用MATLAB需要的配置已经在<Visual Studio调用MATLAB的配置>一文中给出了详细的步骤,本文将介绍混合编程的示例. 在C中调用MATLAB,据 ...

最新文章

  1. Supervisor 进程管理工具
  2. mysql 平均月份_Mysql按月份统计和按时段统计SQL
  3. JAVA 构造 MAP 并初始化 MAP、定义时就初始化
  4. jQuery ajax实现
  5. LibreOffice去重复数据
  6. cuSPARSE库:(八)cusparseGetStream()
  7. c#里面的combobox在代码中怎么根据它的text获取它的index?
  8. java+编辑距离自动机_编辑距离,重叠,组装算法和python程序.pptx
  9. 河北工程大学计算机科学与技术分数线,河北工程大学计算机科学与技术专业2016年在河南理科高考录取最低分数线...
  10. 为什么说索引会加速查找过程
  11. 猿编程python,python编程猿
  12. 工业机器人常用编程语言有哪些
  13. 萤石云平台接入_新手上路 老司机教你配置萤石云
  14. android手机连不上wifi密码,修改wifi密码后手机连不上_修改wifi密码后手机不能上网-192路由网...
  15. 别瞎扯,元宇宙就是没有切实发展?
  16. 《矩阵理论与方法》lambda矩阵及Jordan标准形
  17. JAVA dwg转pdf的正确解法
  18. TOP100summit:【分享实录】京东1小时送达的诞生之路
  19. 心理实验应用计算机的优缺点,发展心理学研究方法发展的新趋势
  20. 前端通过【bitly】Api,将长链接转换短连接

热门文章

  1. 又一大波僵尸向社交网络来了
  2. 基于python的股票数据的读取及可视化(K线图)
  3. nanachi 使用指南
  4. AirtestIDE无线连接手机
  5. 破壳之旅——记鸟蛋的发育
  6. 灵犀互娱 | 2021 校招笔试
  7. MyBatis的sql动态传入表名和字段名,并判断是否为空
  8. Andorid PopWindow使用总结
  9. word2vec简单总结
  10. mysql标量函数,SQL Server标量函数