1、通用单例类
1 #ifndef _SINGLETON_H
2 #define _SINGLETON_H
3
4 namespace GameGeneric
5 {
6 template<class T>
7 class Singleton
8 {
9 public:
10 static T* instance()
11 {
12 if ( !_instance )
13 {
14 _instance = new T;
15 }
16 return _instance;
17 }
18
19 protected:
20 // 使用保护构造是为了让用户不能在栈上声明一个实例
21 Singleton() {}
22
23 private:
24 static T* _instance; // 实例静态指针
25 };
26
27 // 静态实例指针初始化
28 template <class T> T* Singleton<T>::_instance = NULL;
29
30 }
31
32 #endif
//使用的时候只需要单件类继承此模板即可。
class Test : public Singleton<Test >{...};
2、Dll(so)动态加载
1 #ifndef __LIB_DEF_H_
2 #define __LIB_DEF_H_
3
4 namespace GameGeneric
5 {
6 // DLL对象创建辅助类
7 template<const TCHAR*& szFileName>
8 class DllApi
9 {
10 public:
11 static BOOL Load()
12 {
13 if( !m_h )
14 {
15 m_h = ::LoadLibrary(szFileName);
16 }
17 return m_h != NULL;
18 }
19 static void Unload()
20 {
21 if( m_h )
22 {
23 ::FreeLibrary(m_h);
24 }
25 m_h = NULL;
26 }
27 protected:
28 static HMODULE m_h;
29 };
30 template<const TCHAR*& szFileName> HMODULE DllApi<szFileName>::m_h;
31
32 //库文件前后缀
33 #ifdef WIN32
34 #define __DLL_PREFIX _T("")
35 #define __DLL_SUFFIX _T(".dll")
36 #else
37 #define __DLL_PREFIX _T("lib")
38 #define __DLL_SUFFIX _T(".so")
39 #endif
40
41 // 声明DLL文件名常量
42 #define DECLARE_DLL_FILE(module) extern "C" const TCHAR* module;
43
44 // 定义DLL文件名常量
45 #if !defined(_LIB) && !defined(_USE_STATIC_LIB)
46 #define DEFINE_DLL_FILE(module) extern "C" const TCHAR* module = _T("./")""__DLL_PREFIX""_T(#module)""__DLL_SUFFIX;
47 #else
48 #define DEFINE_DLL_FILE(module)
49 #endif
50 }
51
52 #endif
本例中使用了LoadLibrary,是windows的实现方法,在后面平台相关处理中,将linux的函数封装,和windows同名。
此模板使用方法很简单:
1 #if defined(_LIB) || defined(_USE_STATIC_LIB) // 静态库版本
2 #ifndef _LUA_ENGINE_API
3 #define _LUA_ENGINE_API IMPORT_API
4 #pragma comment(lib, MAKE_LIB_NAME(LuaEngine))
5 #endif
6
7 _LUA_ENGINE_API ILuaEngine* GlobalLuaEngine();
8 #else
9 DECLARE_DLL_FILE(LuaEngine);
10 class GlobalLuaEngine : public DllApi<LuaEngine>
11 {
12 typedef ILuaEngine* (*CREATE_PROC)();
13 ILuaEngine* m_p;
14 public:
15 GlobalLuaEngine() : m_p(NULL)
16 {
17 Load();
18 static CREATE_PROC func;
19 if(func == NULL) func = (CREATE_PROC)::GetProcAddress(m_h, "GlobalLuaEngine");
20 if(func != NULL) m_p = func();
21 }
22 operator ILuaEngine* (){ return m_p; }
23 ILuaEngine* operator ->(){ return m_p; }
24 };
25 #endif
上面代码所示,LuaEngine是一个dll,我们在加载它的时候,使用了一个额外的类,在他的构造函数里面加载了共享库。而且在应用级上也与平台无关。
3、跨平台的若干处理
Windows的处理相当简单,只是定义一些简单的宏:
1 // gwindef.h : windows开发定义文件
2 #ifndef __G_WIN_DEF_H_
3 #define __G_WIN_DEF_H_
4
5 #include <windows.h>
6 #include <process.h>
7 #include <tchar.h>
8 #include <unknwn.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11
12 #define SYS_API WINAPI
13 #define STD_CALL __stdcall
14 #if !defined(_LIB)
15 #define EXPORT_API extern "C" _declspec(dllexport)
16 #else
17 #define EXPORT_API extern "C"
18 #endif
19 #if !defined(_LIB) && !defined(_USE_STATIC_LIB)
20 #define IMPORT_API extern "C" _declspec(dllimport)
21 #else
22 #define IMPORT_API extern "C"
23 #endif
24
25 #endif // ndef __G_WIN_DEF_H_
为了开发的时候去除平台无关性,在Linux的开发中,我们需要做一些包装,使其在开发过程中和window代码一致,如下:
1 // glindef.h : linux开发定义文件
2 #ifndef __G_LIN_DEF_H_
3 #define __G_LIN_DEF_H_
4 //
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <wchar.h>
9 #include <unistd.h>
10 #include <pthread.h>
11 #include <semaphore.h>
12 #include <errno.h>
13 #include <sys/times.h>
14 #include <time.h>
15 #include <dlfcn.h>
16 #include <sys/types.h>
17 #include <linux/unistd.h>
18
19 inline _syscall0(pid_t, gettid) /* Using syscall(2) may be preferable; see intro(2) */
20
21 #ifdef UNICODE
22 #define _T(str) L##str
23 #else
24 #define _T(str) str
25 #endif
26
27 #define TRUE 1
28 #define FALSE 0
29
30 #define MAX_PATH 256
31
32 #define SYS_API
33 #define STD_CALL
34 #define EXPORT_API extern "C"
35 #define IMPORT_API extern "C"
36
37 /// HRESULT 常量定义
38 typedef long HRESULT;
39 enum HResult
40 {
41 S_OK = ((HRESULT)0x00000000), /**< 成功,值为0 */
42 S_FALSE = ((HRESULT)0x00000001), /**< 成功,但值为1 */
43 E_FAIL = _HRESULT_TYPEDEF_(0x80004005), /**< 未定义错误 */
44 E_NOTIMPL = _HRESULT_TYPEDEF_(0x80004001), /**< 接口未实现 */
45 E_OUTOFMEMORY = _HRESULT_TYPEDEF_(0x8007000E), /**< 内存不足 */
46 E_INVALIDARG = _HRESULT_TYPEDEF_(0x80070057), /**< 无效参数 */
47 E_NOINTERFACE = _HRESULT_TYPEDEF_(0x80004002), /**< 接口不存在 */
48 E_POINTER = _HRESULT_TYPEDEF_(0x80004003), /**< 无效指针 */
49 E_HANDLE = _HRESULT_TYPEDEF_(0x80070006), /**< 无效句柄 */
50 E_ABORT = _HRESULT_TYPEDEF_(0x80004004), /**< 操作被取消 */
51 E_ACCESSDENIED = _HRESULT_TYPEDEF_(0x80070005), /**< 访问拒绝 */
52 E_PENDING = _HRESULT_TYPEDEF_(0x8000000A), /**< 操作被挂起 */
53 E_UNEXPECTED = _HRESULT_TYPEDEF_(0x8000FFFF) /**< 未预料的错误 */
54 };
55
56 /// 判定 HRESULT 值是否为成功值
57 #define SUCCEEDED(Status) ((HRESULT)(Status) >= 0)
58 /// 判定 HRESULT 值是否为失败值
59 #define FAILED(Status) ((HRESULT)(Status) < 0)
60
61 /// GUID 类型定义
62 /**
63 要定义 GUID 常量请使用 GUID 专门的生成工具(比如 VS 携带的 guidgen.exe 程序)来生成,
64 以确保其唯一性。
65 接口 ID(IID), 类 ID(CLSID)均为 GUID 的别名*/
66 struct GUID
67 {
68 unsigned long Data1;
69 unsigned short Data2;
70 unsigned short Data3;
71 unsigned char Data4[8];
72 };
73
74 typedef GUID IID;
75 typedef GUID CLSID;
76 #define REFGUID const GUID&
77 #define REFIID const IID&
78 #define REFCLSID const CLSID&
79
80 /// 判断两个 GUID 是否相等(内联版)
81 inline BOOL InlineIsEqualGUID(REFGUID rguid1, REFGUID rguid2)
82 {
83 return ((long*)&rguid1)[0] == ((long*)&rguid2)[0] &&
84 ((long*)&rguid1)[1] == ((long*)&rguid2)[1] &&
85 ((long*)&rguid1)[2] == ((long*)&rguid2)[2] &&
86 ((long*)&rguid1)[3] == ((long*)&rguid2)[3];
87 }
88
89 /// 判断两个 GUID 是否相等
90 inline BOOL IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
91 {
92 return !memcmp(&rguid1, &rguid2, sizeof(GUID));
93 }
94
95 #define CopyMemory(dest, src, len) memcpy((dest), (src),(len))
96 #define ZeroMemory(dest, len) memset((dest), 0, (len))
97 #define FillMemory(dest, len, value) memset((dest), value, (len))
98 #define GetCurrentThreadId gettid
99 #define OutputDebugString(str) tprintf(_T("%s"), str)
100 #define LoadLibrary(file) dlopen(file, RTLD_NOW)
101 #define FreeLibrary dlclose
102 #define GetProcAddress dlsym
103
104 inline int GetLastError()
105 {
106 return errno;
107 }
108
109 inline DWORD GetTickCount()
110 {
111 static int clkTck = 0;
112 if(clkTck == 0) clkTck = 1000 / ::sysconf(_SC_CLK_TCK);
113 return (DWORD)::times(NULL) * clkTck; // 不能溢出
114 }
115
116 inline void Sleep(DWORD ms)
117 {
118 struct timespec req, rem;
119 req.tv_sec = ms / 1000; req.tv_nsec = (ms % 1000) * 1000000;
120 while(::nanosleep(&req, &rem) && ::GetLastError() == EINTR) req = rem;
121 }
122
123 inline long InterlockedIncrement(long volatile* v)
124 {
125 long src = 1;
126 /* Modern 486+ processor */
127 __asm__ __volatile__(
128 "lock xaddl %0, %1;"
129 :"=r"(src), "=m"(*v)
130 :"0"(src));
131 return src + 1;
132 }
133
134 inline long InterlockedDecrement(long volatile* v)
135 {
136 long src = -1;
137 /* Modern 486+ processor */
138 __asm__ __volatile__(
139 "lock xaddl %0, %1;"
140 :"=r"(src), "=m"(*v)
141 :"0"(src));
142 return src - 1;
143 }
144
145 #define stricmp strcasecmp
146
147 #include <ctype.h>
148 inline void strupr(char *s)
149 {
150 while (*s)
151 {
152 *s = toupper((unsigned char) *s);
153 s++;
154 }
155 }
156
157 inline void strlwr(char *s)
158 {
159 while (*s)
160 {
161 *s = tolower((unsigned char) *s);
162 s++;
163 }
164 }
165
166 #endif // ndef __G_LIN_DEF_H_
功能是对一些常用函数改装成Windows相关函数的名字