• 在 C# CLR 中学习 C++ 之了解 extern


    ## 一:背景

    CLR 源码中有很多的 `extern` 和 `extern "C"` 这样的关键词,比如下面这些代码:

    ``` C++

    extern size_t gc_global_mechanisms[MAX_GLOBAL_GC_MECHANISMS_COUNT];

    extern DWORD g_dwHandles;

    // The single GC heap instance, shared with the VM.
    extern IGCHeapInternal* g_theGCHeap;

    extern PTR_VOID GetUnwindDataBlob(TADDR moduleBase, PTR_RUNTIME_FUNCTION pRuntimeFunction, /* out */ SIZE_T * pSize);

    extern "C" uint32_t* g_gc_card_table;
    extern "C" uint8_t* g_gc_lowest_address;

    extern "C"
    {
        uint8_t *g_gc_sw_ww_table = nullptr;
        bool g_gc_sw_ww_enabled_for_gc_heap = false;
    }

    ```

    那这些都是什么意思呢? 为了更好的学习 CLR,这些还是要简单了解一下的。


    ### 一:extern 

    ### 1. 变量定义和变量引用

    在 C# 中并没有听说过有 `extern` 这种概念,其实变量可以有两种方式存在。

    1) 变量定义

    2) 变量引用

    变量定义概念很简单,定义就得给它分配内存空间,比如下面这样:

    ``` C#

    #include
    #include

    int k = 10;
    const char* ch = "abcde";

    int main()
    {
        printf("ch=%d", strlen(ch));
    }

    ```

    接下来看下 `变量引用`,它其实和 `文件引用` 以及 C# 的 `using` 概念相似,即把其他文件中的变量引入到本文件,目的就是为了使用,比如在 `Arts` 文件下定义了一个 `page.cpp` 文件,截图如下:

    ![](https://hxc-test.oss-cn-hangzhou.aliyuncs.com/PYZ/20220901103308.png)


    为了能够在 `ConsoleApplication3.cpp` 中使用 `int i` ,那怎么办呢? 这时候就需要用 extern 引入了。

    ![](https://hxc-test.oss-cn-hangzhou.aliyuncs.com/PYZ/20220901103532.png)

    因为 VisualStudio 可以帮我们自动链接,所以这里就不需要 `#include "page.cpp"` 导入,接下来把程序跑起来,就可以观察到程序的结果。

    ![](https://hxc-test.oss-cn-hangzhou.aliyuncs.com/PYZ/20220901103648.png)
     
    如果不用 `extern` 导入的话,就会出现编译错误,说 `n` 是未定义的。

    ![](https://hxc-test.oss-cn-hangzhou.aliyuncs.com/PYZ/20220901103829.png)


    还有一点要注意 `extern` 是对外部变量的一个引用,它不会生成任何汇编代码。

    ### 2. extern "C"

    要理解这个关键词,首先要明白 `方法符号` 的概念,因为 C 和 C++ 在给方法生成符号的逻辑是不一样的,比如同样的一个 `fly` 函数。

    ``` C++

    #include

    void fly() {
        printf("hello world");
    }

    int main()
    {
    }

    ```

    在 C 中生成的函数名还是 `fly` 字样。

    ![](https://hxc-test.oss-cn-hangzhou.aliyuncs.com/PYZ/20220901105836.png)

    可 C++ 不这么认为,它会对 fly 函数名重新编排,比如下面的 `?fly@@YAXXZ`。

    ![](https://hxc-test.oss-cn-hangzhou.aliyuncs.com/PYZ/20220901105656.png)

    如果你在 C++ 中混用 C 的话,这时候就有理念冲突,那在`C++`中让某些函数名还是原样生成有办法吗?当然可以了,这就需要使用 `extern "C"` ,参考如下代码:


    ``` C++

    // page.cpp
    #include

    extern "C"
    {
        void fly() {
            printf("hello");
        }
    }

    void fly2() {
        printf("hello");
    }

    ```

    然后可以在 `ConsoleApplication.cpp` 中引入进来。


    ``` C++

    // ConsoleApplication.cpp

    #include

    extern "C" void fly();

    extern void fly2();

    int main()
    {
        fly();

        fly2();

        return 0;
    }

    ```

    ![](https://hxc-test.oss-cn-hangzhou.aliyuncs.com/PYZ/20220901113642.png)

    好了,本篇就简单说这么多吧,相信再回头看 CLR 中的那些 extern 关键词,你会有一些新的理解。

  • 相关阅读:
    【计数DP】CF1794D
    Springboot毕业设计毕设作品,个人博客系统设计与实现
    SpringMVC常用注解的详细解析
    SkipList(跳表)
    Selenium 隐藏浏览器指纹特征的几种方式
    因子模型套利定价理论APT的应用
    Mysql集群及高可用-Mysql高可用MHA9
    【日积月累】后端刷题日志
    [翻译]理解Postgres的IOPS:为什么数据即使都在内存,IOPS也非常重要
    模拟信号隔离放大器PCB焊接模块电压电流信号变送0-5v0-10v4-20mA0-20mA1-5v0-12v0-24v
  • 原文地址:https://blog.csdn.net/huangxinchen520/article/details/126658116