当前位置:   article > 正文

在C中调用C++函数_c调用c++函数

c调用c++函数

由于C编译器与C++编译器之间的区别十分巨大,因此二者之间不可以直接互相调用各自的函数接口。但是,使用extern "C"可以实现在C代码中调用C++函数的功能,反之亦可。extern "C"告诉C++编译器,将花括号中的代码按照C语言的规则进行编译与链接。

在本篇文章中,笔者展示了利用C代码调用C++接口的一个示例。实现的功能有:C代码获取C++对象指针,并通过对象指针调用对象函数(包括构造函数和析构函数)。
示例分为5个文件:

CppPrint.cpp
CppPrint.h
CWrapper.cpp
CWrapper.h
CallCpp.c

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

其中CppPrint.cpp中是C++代码的实现,其中用iostream实现了打印Hello world!的功能。这部分的代码没有需要特殊说明的地方,属于一般的C++实现。

/*
 * CppPrint.h
 *
 */
#ifndef CPP_PRINT_H
#define CPP_PRINT_H
#include <string>
class Printer {
public:
    Printer();
    Printer(char* str);
    ~Printer();
    void print();
    void print(char* str);
private:
    std::string mString;
};

#endif // CPP_PRINT_H


/*
 * CppPrint.cpp
 *
 */
#include <iostream>
#include <string>
#include "CppPrint.h"

Printer::Printer()
: mString(""){
    std::cout << "Printer@[" << this << "] is constructed."<< std::endl;
}

Printer::Printer(char* str)
: mString(str) {
    std::cout << "Printer@[" << this << "] is constructed."<< std::endl;
}

Printer::~Printer() {
    std::cout << "Printer@[" << this << "] is destructed."<< std::endl;
}

void Printer::print() {
    std::cout << mString << std::endl;
}

void Printer::print(char* str) {
    if (NULL != str) {
        mString = std::string(str);
    }
    std::cout << mString << std::endl;
}

  • 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
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

CWrapper.cpp是利用extern "C"对C++函数的封装。这里有2点需要特殊说明。首先,C++传递给C的对象指针必须以结构体指针的形式存在,否则C语言的编译器会报错。其次,结构体中只可以包含对象指针,不可以直接包含对象示例。若包含的是对象实例,在C代码执行的时候会发生段错误(Segment Fault)。

/*
 * CWrapper.h
 *
 */
#ifndef C_WRAPPER_H
#define C_WRAPPER_H

#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

struct Printer4C;
typedef struct Printer4C* PrinterRef;
PrinterRef getPrinter(char* str);
void print(PrinterRef ref);
void deletePrinter(PrinterRef ref);

#ifdef __cplusplus
}
#endif

#endif // C_WRAPPER_H


/*
 * CWrapper.cpp
 *
 */
#include <iostream>
#include <cstring>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "CppPrint.h"
#include "CWrapper.h"

#ifdef __cplusplus
extern "C" {
#endif

struct Printer4C {
    Printer* obj;
};

PrinterRef getPrinter(char* str) {
    PrinterRef ref = (PrinterRef) malloc(sizeof(struct Printer4C));
    if (NULL == str || strlen(str) <= 0) {
        ref->obj = new Printer("Hello world!");
    } else {
        ref->obj = new Printer(str);
    }
    return ref;
}

void print(PrinterRef ref) {
    ref->obj->print();
}

void deletePrinter(PrinterRef ref) {
    delete ref->obj;
    free(ref);
}

#ifdef __cplusplus
}
#endif

  • 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
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69

在C文件中获取C++对象指针,并利用对象指针调用成员函数。根据CWrapper的实现,当获取printer时没有传入有效的字符串时,会将打印的内容默认设为“Hello world!”。

/*
 * CallCpp.c
 *
 */
#include "CWrapper.h"

int main() {
    PrinterRef ref1 = getPrinter("");
    PrinterRef ref2 = getPrinter("Welcome!");
    print(ref1);
    print(ref2);
    deletePrinter(ref1);
    deletePrinter(ref2);
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

编译动态库。
$ g++ -fPIC -shared CppPrint.cpp CppPrint.h CWrapper.cpp CWrapper.h -o libCppPrint.so
将libCppPrint.so复制到/usr/lib下。
$ sudo cp libCppPrint.so /usr/lib
编译C代码
$ gcc CallCpp.c -lCppPrint -o CallCpp
执行程序
$ ./CallCpp
控制台输出

Printer@[0x25b0030] is constructed.
Printer@[0x25b00a0] is constructed.
Hello world!
Welcome!
Printer@[0x25b0030] is destructed.
Printer@[0x25b00a0] is destructed.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

PS:
实验环境:
Ubuntu 14.04 LTS 64位
gcc与g++的版本均为4.4.7

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/194918
推荐阅读
相关标签
  

闽ICP备14008679号