C++入门>>连接规范---extern “C“

简介:

@[TOC]

前言:

  • 本文介绍C++程序中的连接规范》》extern “C”
  • 博主收集的资料New Young,连载中。
  • 博主收录的问题:New Young
  • 转载请标明出处:New Young

背景

  • 在使用不同编程语言进行软件的开发时,需要统一变量,函数名等的链接规范。
  • 如果C++项目中包含C静态库或者动态库,如果你直接包含C的库,那么因为C++的==内部名称修饰==和C的==内部名称修饰==是不同的,在程序的==链接环节==确定调用函数的==地址==就出问题了。当然C项目中包含C++库也会出现这种问题

image-20220317221758341

C++编译器对标识符的修饰导致了,当链接时,去用修饰的标识符去C静态库查找时找不到的情况。C的标识 符是 _StackPush().
  • 那么当如何解决呢?用C++特殊关键字 extern “C”.下面用程序来实现和这个过程。

内部名称修饰

image-20220317212123482

extern “C”

  • extern ”C“ C++编译器可以识别而C编译器不可以识别,这也是C++项目包含C库和 C项目包含C++项目的有些地方不同。
  • extern “C”会告诉编译器,所包含的内容在 ==链接确定调用函数地址时== 要用 C规则(标识符前加一个 “_”)改变标识符的内部名称。》》这个地方可以理解为 编译器在编译时遇到extern “C”时就对其包含的标识符进行的标记 ,这样在链接调用时就能知道那些标识符该修改了。
  • extern “C” 可以对某一个函数进行修饰,也可以对一段代码修饰。
extern "C" void fun();
extern "C" void swap();
extern "C"
{
   void fun();
   void swap();
}

C++项目调用C静态库

C静态库的生成

这里我用栈的2个文件 stack.cpp和stack.h

image-20220317215007851

C++项目中C静态库的包含于配置、

包含

image-20220317221557375

配置一

image-20220317223758825

配置二

image-20220317223957195

效果

image-20220317224243207

C项目调用C++库

C++静态库的生成

  • 因为==C无法识别extern ”C"==,因此需要在==C++库==中进行部分修饰。
  • 修饰的目的是,在C++库中使用C编译器,这样C++库中标识符就是用C修饰的内部名称,在C项目链接这个库时,就不用担心链接问题—C++库中的标识符是C的标识符。
  • 这里用预处理指令来处理程序。
  • 这里也需要C++库文件进行修饰,否则C项目包含C++库时是无法C++函数库的

    #ifdef  __cplusolus
    #include<iostream>
    using namespace std;
    #endif //  __cplusolus
  • 一种思考是:用extern “c”包含所有要用C编译器处理的代码。

    //方式一:
    #ifdef __cplusplus
    extern "C"
    {
    #endif
    
        void StackInit(stack * s);//初始化 
        void StackPush(stack * s, SDateType x);//入栈
        注意sz始终指向入完元素后的下一个位置
        void StackPop(stack * s);//出栈
            只需要sz--就行
            1.数据可以被覆盖
            2.动态开辟的连续内存不允许在中间任何地方free
        void StackPrint(stack * s);//打印
        void StackDestroy(stack * s);//销毁
        SDateType StackTop(stack * s);//取栈顶元素
        bool StackEmpty(stack * s);//判断是否为空,因为sz的特殊性,当sz为0,代表栈空
            获取栈中有效元素个数 
        int StackSize(stack * ps);
    #ifdef __cplusplus
    }
    #endif
    
  • 另外一种是在每条指令前加extern “C”

    #ifdef __cplusplus
    #define EXTERN_C extern "C"
    #else
    #define EXTERN_C 
    #endif
    EXTERN_C  void StackInit(stack* s);//初始化 
    EXTERN_C     void StackPush(stack* s, SDateType x);//入栈
           //注意sz始终指向入完元素后的下一个位置
    EXTERN_C     void StackPop(stack* s);//出栈
            //只需要sz--就行
            //1.数据可以被覆盖
            //2.动态开辟的连续内存不允许在中间任何地方free
    EXTERN_C     void StackPrint(stack* s);//打印
    EXTERN_C     void StackDestroy(stack* s);//销毁
    EXTERN_C     SDateType StackTop(stack* s);//取栈顶元素
    EXTERN_C     bool StackEmpty(stack* s);//判断是否为空,因为sz的特殊性,当sz为0,代表栈空
           // 获取栈中有效元素个数 
    EXTERN_C     int StackSize(stack* ps);
    

image-20220318105051591

效果

image-20220318105446238

总结

  • 再次感叹提出内部名称修修的神奇。一个修饰解决了很多的问题,编译问题,链接问题,不同模块间的连接规范。
  • 通过连接规范,只给含义机器码的库文件就不用担心源码的流出。
相关文章
|
5月前
|
存储 监控 算法
基于跳表数据结构的企业局域网监控异常连接实时检测 C++ 算法研究
跳表(Skip List)是一种基于概率的数据结构,适用于企业局域网监控中海量连接记录的高效处理。其通过多层索引机制实现快速查找、插入和删除操作,时间复杂度为 $O(\log n)$,优于链表和平衡树。跳表在异常连接识别、黑名单管理和历史记录溯源等场景中表现出色,具备实现简单、支持范围查询等优势,是企业网络监控中动态数据管理的理想选择。
168 0
|
6月前
|
存储 安全 编译器
c++入门
c++作为面向对象的语言与c的简单区别:c语言作为面向过程的语言还是跟c++有很大的区别的,比如说一个简单的五子棋的实现对于c语言面向过程的设计思路是首先分析解决这个问题的步骤:(1)开始游戏(2)黑子先走(3)绘制画面(4)判断输赢(5)轮到白子(6)绘制画面(7)判断输赢(8)返回步骤(2) (9)输出最后结果。但对于c++就不一样了,在下五子棋的例子中,用面向对象的方法来解决的话,首先将整个五子棋游戏分为三个对象:(1)黑白双方,这两方的行为是一样的。(2)棋盘系统,负责绘制画面。
99 0
|
8月前
|
SQL 数据库连接 数据库
在C++的QT框架中实现SQLite数据库的连接与操作
以上就是在C++的QT框架中实现SQLite数据库的连接与操作的基本步骤。这些步骤包括创建数据库连接、执行SQL命令、处理查询结果和关闭数据库连接。在实际使用中,你可能需要根据具体的需求来修改这些代码。
505 14
|
10月前
|
存储 缓存 C++
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
|
9月前
|
存储 分布式计算 编译器
C++入门基础2
本内容主要讲解C++中的引用、inline函数和nullptr。引用是变量的别名,与原变量共享内存,定义时需初始化且不可更改指向对象,适用于传参和返回值以提高效率;const引用可增强代码灵活性。Inline函数通过展开提高效率,但是否展开由编译器决定,不建议分离声明与定义。Nullptr用于指针赋空,取代C语言中的NULL。最后鼓励持续学习,精进技能,提升竞争力。
|
编译器 C++
C++入门12——详解多态1
C++入门12——详解多态1
151 2
C++入门12——详解多态1
|
C++
C++入门13——详解多态2
C++入门13——详解多态2
226 1
|
存储 C++ 容器
C++入门9——list的使用
C++入门9——list的使用
166 1
|
C语言 C++ 容器
C++入门7——string类的使用-1
C++入门7——string类的使用-1
118 0