熟悉linux内核编程的应该知道内核模块有一个宏叫 module_init,当内核模块被静态编译到内核后,会在内核init阶段调用每个被module_init声明过的函数。这是如何实现的呢?其实是用到了链接器的特性。具体可参考

https://blog.csdn.net/lu_embedded/article/details/51432616

大致就是告诉连接器将函数指针放到一个特定的程序段,然后在需要的时候遍历这个程序段,拿到每个函数指针,然后调用。

那么MSVC有没有这样的特性呢,搜索了一番,答案是有的,具体可参考

https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-initialization?redirectedfrom=MSDN&view=msvc-160

原理基本上是一样的,只不过是调用时机是VC runtime。

网上还找到了利用gcc runtime 和 vc runtime实现的跨平台INITIALIZER

    // Initializer/finalizer sample for MSVC and GCC/Clang.// 2010-2016 Joe Lowe. Released into the public domain.
#include <stdio.h>
#include <stdlib.h>#ifdef __cplusplus#define INITIALIZER(f) \static void f(void); \struct f##_t_ { f##_t_(void) { f(); } }; static f##_t_ f##_; \static void f(void)
#elif defined(_MSC_VER)#pragma section(".CRT$XCU",read)#define INITIALIZER2_(f,p) \static void f(void); \__declspec(allocate(".CRT$XCU")) void (*f##_)(void) = f; \__pragma(comment(linker,"/include:" p #f "_")) \static void f(void)#ifdef _WIN64#define INITIALIZER(f) INITIALIZER2_(f,"")#else#define INITIALIZER(f) INITIALIZER2_(f,"_")#endif
#else#define INITIALIZER(f) \static void f(void) __attribute__((constructor)); \static void f(void)
#endifstatic void finalize(void)
{printf( "finalize\n");
}INITIALIZER( initialize)
{printf( "initialize\n");atexit( finalize);
}int main( int argc, char** argv)
{printf( "main\n");return 0;
}

另外,我也实现了一个简单的MSVC版本,如下。

#include <windows.h>//以下内容可放到公共头文件
#pragma section(".MYINIT$A", read)
#pragma section(".MYINIT$P", read)
#pragma section(".MYINIT$Z", read)
typedef void (*PFN_INIT)(void);#define _INIT_FN(fn, pre) \static void fn(void); \__declspec(allocate(".MYINIT$P")) PFN_INIT fn##_ = fn; \__pragma(comment(linker,"/include:" pre #fn "_")) \static void fn(void)
#ifdef _WIN64
#define INIT_FN(fn) _INIT_FN(fn, "")
#else
#define INIT_FN(fn) _INIT_FN(fn, "_")
#endif//以下内容放到 main 文件
__declspec(allocate(".MYINIT$A")) int __myinit_a = 0;
__declspec(allocate(".MYINIT$Z")) int __myinit_z = 0;void CallInitFn(void)
{PFN_INIT *start = (PFN_INIT *)&__myinit_a;PFN_INIT *end = (PFN_INIT *)&__myinit_z;while(start < end){if(*start){(*start)();}start++;}
}int main(int argc, char *argv[])
{CallInitFn();Sleep(1000);
}//以下INIT函数可分散放到不同的源文件
INIT_FN(init3)
{OutputDebugStringA("init3\n");
}INIT_FN(init4)
{OutputDebugStringA("init4\n");
}

GCC和MSVC的INITIALIZER的实现相关推荐

  1. 代码从GCC到MSVC的移植

    代码从GCC到MSVC的移植 要把一个项目的build系统从gcc移植到MSVC,困难之一在于源码中使用了gcc extension(http://gcc.gnu.org/onlinedocs/gcc ...

  2. C代码从GCC到MSVC的移植

    原文地址:http://blog.csdn.net/ariesjzj/article/details/7881049 要把一个项目的build系统从gcc移植到MSVC,困难之一在于源码中使用了gcc ...

  3. 总结从linux - windows 上(GCC与MSVC 2015) 移植C或者C++代码时候遇到的编译和链接问题

    解决办法和修改办法的总体思想 1.在代码的语义和功能不变的情况下,进行c->c++的转变,消除编译器的跨平台编译报错问题: 2.遇到编译问题,先看编译器提示信息,然后逐个排查和定位,去解决问题. ...

  4. Linux下的编译(环境是centos6.8 gcc 4.4.7)

    Linux下的编译(环境是centos6.8 gcc 4.4.7) 1. 运行命令:yum install gcc gcc-c++ bzip2 bzip2-devel bzip2-libs Pytho ...

  5. [C] zintrin.h : 智能引入intrinsic函数。支持VC、GCC,兼容Windows、Linux、Mac OS X

    作者:zyl910. 现在很多编译器支持intrinsic函数,这给编写SSE等SIMD代码带来了方便.但是各个编译器略有差异,于是我编写了zintrin.h,智能引入intrinsic函数. 一.各 ...

  6. c++primer 第2章 练习题答案 (尚未完善 陆续补充中 基本上已经完成)

    short int 2个字节 int 2/4字节 long 4/8字节 long long 8字节 其实这个吧 意义不是太大 基本上现在大多数都32/64位机器 所以int基本上最小就都4个字节了  ...

  7. C++反射(Reflection)

    库:boost.hana boost.PFR https://www.cnblogs.com/zengkefu/p/6724323.html An Introduction to Reflection ...

  8. 多人网络游戏服务器开发基础学习笔记 I:基本知识 | 游戏设计模式 | 网游服务器层次结构 | 游戏对象序列化 | 游戏 RPC 框架 | 帧同步和状态同步

    今天继续开新坑,尽管过了很多 Unix 套接字编程的坑,但是实际还是有很多不同场景和性能的需求,以及最服务器架构的内容也就接触过 preforking 和 master 带 worker 而已. 所以 ...

  9. C++ Best Practices (C++最佳实践)翻译与阅读笔记

    击上方"C语言与CPP编程",选择"关注/置顶/星标公众号" 干货福利,第一时间送达! 这个翻译的内容真不错,分享给大家. 翻译原文链接在这里:https:// ...

最新文章

  1. 提升tomcat 性能的经验
  2. 组网中交换机虚拟化技术的应用
  3. resttemplate 文件上传 上传文件
  4. rtsp 分辨率信息_SDP在RTSP、国标GB28181、WebRTC中的实践
  5. 《信息学奥赛一本通》 高精度加法。输入两个正整数,求它们的和。
  6. jenkins 通过自动拉取Gitlab上的代码实现自动更新NGINX
  7. 这 30 个常用的 Maven 命令你必须熟悉
  8. 美国在线计算机硕士申请难度,美国计算机硕士申请条件有哪些?看完这篇文章你就清楚了...
  9. LINUX使用C执行系统命令ping,读取执行结果的崩溃日志
  10. 巴菲特:我们最大的错误不是做错了什么,而是该做的没做
  11. 卫星通信系统按照工作轨道分类
  12. 夺灵者哈卡(Hakkar, the Soulflayer)
  13. java邮箱验证码_Java实现邮箱验证码
  14. python爬取豆瓣top250信息并存入数据库中 | sqlite3
  15. 第七章:CSS3基础---变形旋转 2d/3d、c3边框图片、变形缩放 2d/3d、变形倾斜2d、动画属性
  16. ViewPager嵌套ViewPager,内层ViewPager
  17. iOS_导航栏的navigationBar.hidden与navigationBarHidden的区别
  18. 【数据可视化应用】绘制森林图(附Python和R语言代码)
  19. In a case you entered incorrect password, please update it in Keychain Acces
  20. 我近4年的计算机学习经历

热门文章

  1. esxi服务器接移动硬盘,esxi添加usb移动硬盘存储数据
  2. vue 分享给好友 点击分享按钮_基于vue+leaflet+echart的足迹分享评论平台
  3. c语言实现文件数据删除视频,如何用c语言实现删除文件中指定的数据;例如
  4. Buuctf(pwn) ciscn_2019_n_5
  5. python教程:使用生成器重构提取数据方法来优化爬虫代码
  6. python模块初始与time、datetime及random
  7. c#rs232与三菱通讯_MCGS 与 FX3U PLC 之间的无线通讯实例
  8. pythonslice_shift_Pandas 解决dataframe的一列进行向下顺移问题
  9. ps -aux 和ps -elf 区别(查看进程)
  10. python 虚拟环境 virtualenv virtualenvwrapper的使用方法、命令