跨平台
转载请注明出处。https://rhirufxmbcyj.gitlab.io
strdup 和 _strdup 的使用及区别
二者区别:
strdup是POSIX,_strdup是windows特定。 在Unix上,使用的strdup。
跨平台宏定义
在不同操作系统的lib库名字不同的,为了让程序可以多平台,需要在宏定义中判断当前运行操作系统和编译器的类型,动态调整。
- 操作系统判定:
Windows: WIN32 _WIN32
linux: linux __linux __linux__
MAC: __APPLE__
Solaris: __sun
- 编译器判定:
Borland: __BORLANDC__
Codeplay vectorC: __VECTORC__
digital Mars: __DMC__
Gnu: __GNUC__
Intel: __INTEL_COMPILER
Microsoft: _MSC_VER
Pathscale: __PATHSCALE__
Symantec: __SYMANTECC__
Watcom: __WATCOMC__
- 操作系统位数判定:
Linux_x32: __i386__
Linux_x64: __x86_64__
Windows: _WIN64 定义了就是x64 没定义就是x32
x86: _M_IX86 __INTEL__ __i386__
x86-64: _M_X64 __x86_64__ __AMD64
IA64: __IA64__
DEC Alpha: __ALPHA__
Motorola Power PC: __POWERPC__
Any little endian: __LITTLE_ENDIAN__
Any big endian: __BIG_ENDIAN__
pthread相关
#include <pthread.h>
pthread并非Linux系统的默认库,而是POSIX线程库,在Linux中将其作为一个库来使用,因此加上 -lpthread(或-pthread)以显式链接该库。函数执行错误信息作为返回值返回。
- 创建线程
int pthread_create(
pthread_t *tidp,
const pthread_attr_t *attr,
(void*)(*start_rtn)(void*),
void *arg);
第一个参数为指向线程标识符的指针。
第二个参数用来设置线程属性。
第三个参数是线程运行函数的起始地址。
最后一个参数是运行函数的参数。
- 等待线程结束
int pthread_join(pthread_t thread, void **retval);
- 互斥锁
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
void *fun1(void *arg)
{
pthread_mutex_t *temp = (pthread_mutex_t *)arg;
pthread_mutex_lock(temp);
for(int i=0;i<5;i++)
{
sleep(5);
}
pthread_mutex_unlock(temp);
return 0;
}
void *fun2(void *arg)
{
pthread_mutex_t *temp = (pthread_mutex_t *)arg;
pthread_mutex_lock(temp);
pthread_mutex_unlock(temp);
return 0;
}
int main()
{
pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER;
pthread_t thread1,thread2;
pthread_create(&thread1,NULL,fun1,&mu);
pthread_create(&thread2,NULL,fun2,&mu);
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
pthread_mutex_destroy(&mu);
return 0;
}
- 示例代码
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥锁*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*初始化条件变量*/
void *thread1(void *);
void *thread2(void *);
int i=1;
int main(void)
{
pthread_t t_a;
pthread_t t_b;
pthread_create(&t_a,NULL,thread1,(void *)NULL);/*创建进程t_a*/
pthread_create(&t_b,NULL,thread2,(void *)NULL); /*创建进程t_b*/
pthread_join(t_a, NULL);/*等待进程t_a结束*/
pthread_join(t_b, NULL);/*等待进程t_b结束*/
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
exit(0);
}
void *thread1(void *junk)
{
for(i=1;i<=6;i++)
{
pthread_mutex_lock(&mutex);/*锁住互斥量*/
printf("thread1: lock %d/n", __LINE__);
if(i%3==0){
printf("thread1:signal 1 %d/n", __LINE__);
pthread_cond_signal(&cond);/*条件改变,发送信号,通知t_b进程*/
printf("thread1:signal 2 %d/n", __LINE__);
sleep(1);
}
pthread_mutex_unlock(&mutex);/*解锁互斥量*/
printf("thread1: unlock %d/n/n", __LINE__);
sleep(1);
}
}
void *thread2(void *junk)
{
while(i<6)
{
pthread_mutex_lock(&mutex);
printf("thread2: lock %d/n", __LINE__);
if(i%3!=0){
printf("thread2: wait 1 %d/n", __LINE__);
pthread_cond_wait(&cond,&mutex);/*解锁mutex,并等待cond改变*/
printf("thread2: wait 2 %d/n", __LINE__);
}
pthread_mutex_unlock(&mutex);
printf("thread2: unlock %d/n/n", __LINE__);
sleep(1);
}
}
跨平台踩坑
- printf("%s",a);a不能为NULL否则会报错
- Visual GDB(后面使用VG表示) 调试某一个测试程序。VG不能指定编译和调试某一个程序(比如gtest程序),
如果需要调试指定的程序需要在VisualGDB Project Properties ->Debug setting ->debug->Debugged executable 中设置启动的程序就可以调试指定的程序了
- VG运行制定gtest 在VisualGDB Project Properties ->Debug setting ->debug->Main executable arguments 中指定
gtest的名称就可以运行指定路径的gtest --gtest_filter=case2.*
- linux long 和 long long 都是8字节,windows下的long是4字节,需要把windows下的long改成int使用
- visualGDB打开的工程中不能识别include目录,需要在 工程->右键属性->配置属性->VC++目录->包含目录中手动把src目录添加进去,否则inlcude的时候需要使用…去寻找完整路径。
例如 不配置的话 #include "base/base.h"就不能识别到,需要使用#include “…/base/base.h”
- CMakeLists.txt中依赖静态库语句中,被依赖的库名需放在依赖库名后
例如 target_link_libraries(main test1 test2 test3 test4)
test2依赖test4,test4就需要放test2后边
- linux和mac中没有类似windows中的_DEBUG宏
linux下动态库去符号(仅适用动态库):
原文:https://blog.csdn.net/passers_b/article/details/7582535
推荐第二种方法
1、使用GCC 的C++ visibility 支持。
把__attribute__ ((visibility (“default”))) 放置在你希望导出的struct,class,function的声明处,然后修改你的GCC构建参数,使用 -fvisibility=hidden 参数编译每一个源代码文件。GCC编译源代码文件的visibility默认属性是public,所以默认所有符号都导出来了,设置为hidden后然后在需要导出的地方加__attribute__ ((visibility (“default”))),以达到控制导出符号的目的。在跨平台代码的编写中,常使用下面类似的宏定义来简化上述过程。
#if defined _WIN32 || defined __cygwin__
#ifdef buildING_DLL
#ifdef __GNUC__
#define DLL_PUBLIC __attribute__ ((dllexport))
#else
#define DLL_PUBLIC __declspec(dllexport) // Note: actually gcc seems to also supports this syntax.
#endif
#else
#ifdef __GNUC__
#define DLL_PUBLIC __attribute__ ((dllimport))
#else
#define DLL_PUBLIC __declspec(dllimport) // Note: actually gcc seems to also supports this syntax.
#endif
#endif
#define DLL_local
#else
#if __GNUC__ >= 4
#define DLL_PUBLIC __attribute__ ((visibility ("default")))
#define DLL_LOCAL __attribute__ ((visibility ("hidden")))
#else
#define DLL_PUBLIC
#define DLL_LOCAL
#endif
#endif
extern "C" DLL_PUBLIC void function(int a);
class DLL_PUBLIC SomeClass
{
int c;
DLL_LOCAL void privateMethod(); // Only for use within this DSO
public:
Person(int _c) : c(_c) { }
static void foo(int a);
};
2、使用链接参数 --retain-symbols-file 控制静态符号表,–version-script 控制动态符号表,后面都是接含有导出符号的文件的名字。这两个参数在移植windows下的动态库很有用,windows下的DEF文件能控制导出符号,我们可以在linux下的构建脚本中解析DEF生成一个导出符号文件,然后作为retain-symbols-file,version-script的参数。
编译链接方法:gcc a1.c -shared -o liba1.so -Wl,–retain-symbols-file=a1.sym -Wl,–version-script=a1.map
a1.sym写法:控制.symtab节
func_1
func_3
a1.map写法:控制.dynsym节
{
global:
func_1;
func_2;
local: *;
};
一般编译会加-s将.symtab节删除掉,过删除的话就可以不加a1.sym
相关阅读
最近比较关注WEB页面在不同平台的呈现,于是浏览了多家门户网站分别在PC端、IPAD端、手机端呈现差异,这过程中逐步对网站跨平台呈现
参考文档:https://blog.csdn.net/shenziheng1/article/details/52556763、http://www.mamicode.com/info-detail-2428809.html、百
跨平台通用账号系统|浅析Facebook、Instagram、Messeng
账号系统则好比人体的血液循环系统,起着运输、沟通、交流的作用。如果将APP比喻成人体,那么该APP的主功能就好比是人体的心脏,给予AP
几天前,笔者微信收到了一则朋友圈发来的消息,打开一看原来是清明节期间在广州地王广场所举办的一场“地王广场流浪动物领养日&