目录

  • 前言
  • extern "C"的作用
  • 利用extern "C"给c++ 函数做声明,然后再定义函数,让.c文件可以找到c++的函数
  • c语言调用c++中的全局函数,这里不包含类的概念,直接用,因为是xcode平台建立的c++文件,所以.h文件扩展名变成了.hpp
  • 用c语言的.c文件调用c++ 文件中的类和类方法
  • .hpp头文件
  • .cpp文件,注意,里面包含了一个#include "CppBridging.h"文件,里面的内容就是一个extern "C"的函数声明
  • .c文件的调用
  • demo点击我下载


前言

这篇教程主要讲解了,c语言,如何调用c++的类和类方法,目的是为了用swift调用c++代码的教程做铺垫,因为swift无法直接调动c++代码,但是可以调用c语言代码和oc代码,所以先做了这个教程.作为swift调用c++代码其中一种方法的铺垫教程

extern "C"的作用

首先这个 extern “C” {}是告诉编译器,把这段代码按照C语言的格式进行编译,为啥要这样呢?因为c++有重载,而c语言没有,重载是函数名字相同,但是形参列表不同.

#ifdef __cplusplus
    extern "C"{
#endif
//这里写要C++ 的函数声明
#ifdef __cplusplus
    } //__cplusplus

先解释一下 #ifdef __cplusplus extern “C” ,这个跟#ifdef Debug语法一样,就是如果编译器是 C++ 编译器,那么执行后面的 extern “C”
上面这所有代码意思是:,如果当前编译器是按照c++编译,就把{ }中的内容按照 C语言来编译,这样一来,所有重载的方法,被按照C语言的语法变成了不同名字的方法,而不是相同名字不同参数的方法,这样就解决了C语言编译器无法处理重载的问题.

利用extern "C"给c++ 函数做声明,然后再定义函数,让.c文件可以找到c++的函数

c语言调用c++中的全局函数,这里不包含类的概念,直接用,因为是xcode平台建立的c++文件,所以.h文件扩展名变成了.hpp

//
//  CFn.hpp
//  CProductRunCppClassDemo
//
//  Created by 谭迪文 on 2021/6/26.
//

#ifndef CFn_hpp
#define CFn_hpp

#include <stdio.h>
#ifdef __cplusplus
extern "C"{
#endif
void cPrintFn1(void);//用extern "C" 声明的函数可以被 .c文件调用
void cPrintFn2(void);
#ifdef __cplusplus
} //__cplusplus
#endif

#endif /* CFn_hpp */
//
//  CFn.cpp
//  CProductRunCppClassDemo
//
//  Created by 谭迪文 on 2021/6/26.
//

#include "CFn.hpp"
#include <stdio.h>
void cPrintFn1(void){
    printf("c++文件中的全局函数cPrintFn1()运行\n");
}
void cPrintFn2(void){
    printf("c++文件中的全局函数cPrintFn2()运行\n");
}

用.c文件调用

#include <stdio.h>
#include "CFn.hpp"
#include "CppBridging.h"

int main(int argc, const char * argv[]) {
    // insert code here...
    printf("Hello, World!\n");
    cPrintFn1();
    cPrintFn2();
    return 0;
}

用c语言的.c文件调用c++ 文件中的类和类方法

##思路是把类的创建方法,写成普通的全局方法,然后再用void* 指针,来代替c++的 class 的指针

.hpp头文件

//
//  CPerson.hpp
//  externCDemo
//
//  Created by 谭迪文 on 2021/6/26.
//

#ifndef CPerson_hpp
#define CPerson_hpp

#include <stdio.h>
#include <iostream>
#endif /* CPerson_hpp */

using namespace std;
class CPerson
{
public:
CPerson();
~CPerson();
    string name;
    int age;
    void printTest(void);
private:
};

.cpp文件,注意,里面包含了一个#include "CppBridging.h"文件,里面的内容就是一个extern "C"的函数声明

//
//  CPerson.cpp
//  externCDemo
//
//  Created by 谭迪文 on 2021/6/26.
//

#include "CPerson.hpp"
#include <iostream>
#include "CppBridging.h"
using namespace::std;
CPerson::CPerson()  {
    
}

CPerson::~CPerson()  {
    
}

void CPerson::printTest(void){//创建类的方法
    cout<< "c++ 函数 printTest()运行" <<endl;
}
void* createCPerson(void){
    return new CPerson;
}
void* createCPersonBy(const char* name,int age){ //注意这里不能起名叫createCPerson(const char* name,int age)因为这个要给c语言用,c语言没有重载,会报错Conflicting types for 'createCPerson',命名冲突
    CPerson *p = new CPerson;
    p->name = name;
    p->age = age;
    return p;
}
const char* getCPersonName(void *p){
    return ((CPerson*)p)->name.data();
}

CppBridging.h头件,这个文件里面把c++的函数做了声明,因为要,之所以要单独放在一个文件当中,是因为,一会.c文件也要包含这个头文件,但是.c文件不能包含c++ 的头文件,因为c++的头文件里面声明了类 class关键字,是不能被extern "C"编译成功的.

//
//  CppBridging.h
//  externCDemo
//
//  Created by 谭迪文 on 2021/6/26.
//

#ifndef Header_h
#define Header_h

#ifdef __cplusplus
extern "C"{
#endif

void* createCPerson(void);
void* createCPersonBy(const char* name,int age);
const char* getCPersonName(void *p);
#ifdef __cplusplus
} //__cplusplus
#endif



#endif /* Header_h */

.c文件的调用

//
//  main.c
//  CProductRunCppClassDemo
//
//  Created by 谭迪文 on 2021/6/26.
//

#include <stdio.h>
#include "CFn.hpp"
#include "CppBridging.h"

int main(int argc, const char * argv[]) {
    // insert code here...
    printf("Hello, World!\n");
    void *p = createCPerson();//创建对象
    void *p2 = createCPersonBy("张三", 18);//创建对象并且赋值
    const char * name = getCPersonName(p2);//返回对象成员变量
    printf("name=%s\n",name);
    return 0;
}

demo点击我下载