关于编写c++动态库常用的定义
1. 关于
- 1.1 最近一段时间,写了不少动态库,慢慢的也积累了东西。
- 1.2 之前一直做Windows的动态库,没有做过Linux和OS X的动态库,太缺乏经验了: 代码缺乏 编译器支持的判断、缺乏c++版本判断、缺乏操作系统的判断.... 总之,导致了很多问题。
2. Unicode和ANSI
这个,特别是 call Windows API 很明显,一个Windows API函数提供了 Unicode和ANSI的支持。添加下面的宏支持两种编码:
// to
// c/c++ run time library
#ifdef _UNICODE
#ifndef UNICODE
#define UNICODE
#endif
#endif
// windows
#ifdef UNICODE
#ifndef _UNICODE
#define _UNICODE
#endif
#endif
一个例子,演示需要调用函数CreateFile,它有2个版本:CreateFileA 和 CreateFileW,其第一个参数是设备的名字,可以这样写:
TCHAR *tc_com_name = nullptr;
#ifdef UNICODE
std::wstring wstr = str2wstr(spp._name);
tc_com_name = const_cast<TCHAR *>(wstr.c_str());
#else
tc_com_name = const_cast<TCHAR*>(spp._name.c_str());
#endif // !UNICODE
调用函数CreateFile:CreateFile( tc_com_name, ...) 就好啦。
3. __cplusplus
通常使用这个宏判断c++的版本,但是, Visual Studio X (X = 2003, 2005, 2008 , 2010... 下面简称VS)编译器中,这个默认值一直都是:199711L。官网也说了,目前仅支持VS2017(version 15.7)及以上版本可以添加命令修改, 具体的可以看这里。
使用__cplusplus判断c++版本示例:
#if __cplusplus >= 201103L
#define has_cxx_11
#endif //
4. 动态库导出符
根据操作系统的不同,设置对应的宏(一个例子)
// to definite an export flag
#if defined(_WIN32) || defined(_WIN64) || defined(WIN32)
//----------------------------------------------------------------------
#ifndef _lib_sp_api_
#define _lib_sp_api_ __declspec(dllexport)
#else
#define _lib_sp_api_ __declspec(dllimport)
#endif /// !_lib_pipe_api_
#elif defined(_unix_) || defined(_linux_) || defined(_unix) || defined(_linux) || #elif defined(__APPLE__)
//----------------------------------------------------------------------
#ifndef _lib_sp_api_
#define _lib_sp_api_ __attribute__((visibility ("default")))
#endif /// !_lib_pipe_api_
#endif /// !
5. 编译器判断
可能你需要根据编译器的不同执行某些代码,下面的代码可以帮到你,一个例子
#if defined(__clang__) || defined(__GNUC__)
// clang or gcc(++)
#elif defined(_MSC_VER) // use vs compiler
#if 1900 <= _MSC_VER // 1900 = vs2015
#ifndef has_cxx_11
#define has_cxx_11
#endif //
#endif
#endif
6. 操作系统的判断
可能你还需要对操作系统的判断,比如编写串口通信时,需要call系统api完成相关操作,下面的代码可以帮到你。 一个例子:
#if defined(_WIN32) || defined(_WIN64)
# ifndef os_is_win
#define os_is_win
#else
#endif /// os_is_win
#elif defined(_linux) || defined(_linux_) || defined() || defined (_unix_)
# ifndef os_is_linux
#define os_is_linux
#else
#endif /// os_is_linux
#elif defined(__APPLE__)
#ifndef os_is_apple
#define os_is_apple
#else
#endif /// os_is_apple
#endif //
7.附完整版
copy即可使用
// c/c++ run time library
#ifdef _UNICODE
#ifndef UNICODE
#define UNICODE
#endif
#endif
// windows
#ifdef UNICODE
#ifndef _UNICODE
#define _UNICODE
#endif
#endif
// cpp_version to check if it suppports c++11
//---------------------------------------------------------------------------------------------
#if __cplusplus >= 201103L
#define use_cpp_11
#endif // ! __cplusplus >= 201103L
// compiler
//---------------------------------------------------------------------------------------------
#if defined(__clang__) || defined(__GNUC__)
#define compiler_is_clang
// clang or gcc(++)
#elif defined(_MSC_VER) // use vs compiler
#ifndef compiler_is_vs
#define compiler_is_vs
#endif //! compiler_is_vs
//--------------------------------------------
#if 1900 <= _MSC_VER // 1900 = vs2015
#ifndef use_cpp_11
#define use_cpp_11
#endif //
#endif
#endif //! defined(__clang__) || defined(__GNUC__)
// os
//---------------------------------------------------------------------------------------------
#if defined(_WIN32) || defined(_WIN64)
#ifndef os_is_win
#define os_is_win
#else
#endif // os_is_win
#elif defined(_linux) || defined(_linux_) || defined(__linux) || defined (_unix_)
#ifndef os_is_linux
#define os_is_linux
#else
#endif /// os_is_linux
#elif defined(__APPLE__)
#ifndef os_is_osx
#define os_is_osx
#else
#endif /// os_is_osx
#endif // !defined(_linux) || defined(_linux_) || defined(__linux) || defined (_unix_)
// -----------------------------------------------------------------------------------------
#if defined(os_is_win)
#ifndef _oct_udp_api_export_export_
#define _lib_udp_api_export_ __declspec(dllexport)
#else
#define _lib_udp_api_export_ __declspec(dllimport)
#endif //! _oct_udp_api_export_export_
// -----------------------------------------------------------------------------------------
#elif defined(os_is_linux) || defined(os_is_osx)
#ifndef _oct_udp_api_export_export_
#define _lib_udp_api_export_ __attribute__((visibility("default")))
//#define _oct_udp_api_export_ __attribute__ ((visibility("default")))
#endif // !_oct_udp_api_export_export_
#endif // !os_is_win
关于编写c++动态库常用的定义的更多相关文章
- Delphi调用C# 编写dll动态库
Delphi调用C# 编写dll动态库 编写C#dll的方法都一样,首先在vs2005中创建一个“类库”项目WZPayDll, using System.Runtime.InteropServices ...
- Linux 下Python调用C++编写的动态库
在工程中用到使用Python调用C++编写的动态库,结果报如下错误: OSError: ./extract_str.so: undefined symbol: _ZNSt8ios_base4InitD ...
- linux c++ 加载动态库常用的三种方法
链接库时的搜索路径顺序:LD_LIBRARY_PATH --> /etc/ld.so.conf --> /lib,/usr/lib 方法1. vi .bash_profile 设置环 ...
- makefile编写---.so动态库的生成和调用
http://blog.sina.com.cn/s/blog_559f6ffc0100fl3z.html 动静 http://blog.csdn.net/yuyunliuhen/article/de ...
- 【转】分析Linux和windows动态库
原文地址:http://www.cnblogs.com/chio/archive/2008/11/13/1333119.html 摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Lin ...
- Linux和windows动态库
转载:http://www.cnblogs.com/chio/archive/2008/11/13/1333119.html 态链接库技术实现和设计程序常用的技术,在Windows和Linux系 统中 ...
- C++ 系列:静态库与动态库
转载自http://www.cnblogs.com/skynet/p/3372855.html 这次分享的宗旨是——让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择 ...
- C++静态库与动态库
C++静态库与动态库 这次分享的宗旨是--让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择.这里不深入介绍静态库.动态库的底层格式,内存布局等,有兴趣的同学,推荐一 ...
- c/c++:动态库 静态库 linux/windows 例子 (转)
作者:吴秦出处:http://www.cnblogs.com/skynet/本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名吴秦(包含链接). C++静 ...
随机推荐
- Codeforces 1299D - Around the World(线性基+图论+dp)
Codeforces 题目传送门 & 洛谷题目传送门 一道线性基的综合题 %%%%%% 首先注意到"非简单路径""异或和"等字眼,可以本能地想到线性基. ...
- 水平梯度在sigma坐标对应形式
sigma 坐标变换 一般 \(\sigma\) 坐标转换方程为 \[\sigma = \frac{z-\eta}{D} = \frac{z-\eta}{H+\eta} \] 转换后水深 z 范围由原 ...
- 毕业设计之zabbix---自带模板监控mysql内容
自带模板是不能直接建立连接就可以用的 必须经历一下几步: 建立用户权限: [root@mysql.quan.bbs lib]$mysql -u root -p Enter password: Welc ...
- 普通用户iptables规则持久化,开机自动恢复
本文档对于docker环境下并不适用,docker环境的iptables持久化请参考https://www.cnblogs.com/wiseo/p/15000745.html 添加iptables规则 ...
- 使用 CliWrap 让C#中的命令行交互举重若轻
在代码中进行命令行交互是一个很常见的场景, 特别是在一些CI CD 自动化流程中, 在这之前我们会使用 System.Diagnostics.Process API, 现在有一个更灵活的工具 CliW ...
- 『学了就忘』Linux文件系统管理 — 66、通过图形界面进行LVM分区
目录 1.选择自定义分区 2.分配boot分区 3.创建LVM物理卷 4.生成卷组 5.创建逻辑卷 6.格式化安装 我们先用新安装Linux系统时的图形化界面,来演示一下LVM逻辑卷如何进行分区. 提 ...
- 【每天五分钟大数据-第一期】 伪分布式+Hadoopstreaming
说在前面 之前一段时间想着把 LeetCode 每个专题完结之后,就开始着手大数据和算法的内容. 想来想去,还是应该穿插着一起做起来. 毕竟,如果只写一类的话,如果遇到其他方面,一定会遗漏一些重要的点 ...
- 22 SHELL 获取当前路径
常见的一种误区,是使用 pwd 命令,该命令的作用是"print name of current/working directory",这才是此命令的真实含义,当前的工作目录,这里 ...
- Spark检查点机制
Spark中对于数据的保存除了持久化操作之外,还提供了一种检查点的机制,检查点(本质是通过将RDD写入Disk做检查点)是为了通过lineage(血统)做容错的辅助,lineage过长会造成容错成本过 ...
- LeetCode1579题——圆圈中最后剩下的数字
1.题目描述:0,1,,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字.求出这个圆圈里剩下的最后一个数字.例如,0.1.2.3.4这5个数字组成一个圆圈,从数字0开始每次删 ...