我是靠谱客的博主 风中大叔,最近开发中收集的这篇文章主要介绍将libzdb移植到msvc(Visual Studio 2013)1 资料准备2 编译代码准备3 该库依赖其它库4 建msvc工程(这个不需要我详细写了吧)5 静态库成功编译的修改6 unity编译方式7 关于libzdb_unity工程的说明8 头文件提取,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
开篇提示:本文欢迎转载,但必须注明本文出处,例如:
“该文引用自 CruiseYoung的: 将libzdb移植到msvc(Visual Studio 2013)
http://blog.csdn.net/fksec/article/details/41478947”
否则说明阁下愿意支付以100元人民币每字计的稿费,敬请留意。
1 资料准备
1.1 官方网站:
http://www.tildeslash.com/libzdb/代码托管地址:https://bitbucket.org/tildeslash/libzdb
1.2 开发中代码下载:
https://bitbucket.org/tildeslash/libzdb/downloads
1.3 发布版代码下载(当前发布的版本为3.0):
http://www.tildeslash.com/libzdb/dist/libzdb-3.0.tar.gz
1.4 支持sql server的代码下载(SVN工具下载):
http://code.taobao.org/p/libzdb_dev/src/http://code.taobao.org/svn/libzdb_dev/trunk
1.5 整理后的代码:
https://github.com/CruiseYoung/libzdb_msvc
https://bitbucket.org/cruiseyoung/libzdb_msvc
注:
branch: static 此分支只保证可以生成静态库(在msvc中使用,尚有"typedef struct T *T;"不合语法问题)。
branch: master此分支生成的静态库可以放心使用;此分支将库源代码一个一个的加入自己的工程,同时可支持5种数据库池(具体看宏打开情况)。 推荐用此分支。该分支与作者代码最为接近。
branch: unity 此分支生成的静态库可以放心使用;此分支使用zdb.c文件统一将库源代码加入自己的工程时,同时只能支持一种数据库池(宏同时只能打开一种)。但若使用分支“master”方式加入自己工程时,同时可支持5种数据库池(具体看宏打开情况)。
2 编译代码准备
2.1 获取Time.re、URL.re
从1.2中下载的代码中提取;
2.2 获取Time.c、URL.c
从1.3中下载的代码中提取;
2.3 代码整合准备
2.3.1 将1.3中的代码解压到libzdb-3.0目录(有的软件可能要解压两次,例如7-zip);2.3.2 将1.2中的代码解压到tildeslash-libzdb-581e778d1346目录;2.3.3 将1.4中的代码下载到libzdb_dev目录;2.3.4 整合:
新建libzdb_msvc目录;将libzdb-3.0目录中的所有文件复制到libzdb_msvc目录;将tildeslash-libzdb-581e778d1346目录中所有文件复制并覆盖到libzdb_msvc目录;将libzdb_devsrcdbsqlserver整个目录(当然包含了目录中的文件)libzdb_msvcsrcdb目录。
3 该库依赖其它库
3.1 ws2_32.lib;
3.2 pthreads-win32 http://www.sourceware.org/pthreads-win32/
3.3 MySql Connector/C http://dev.mysql.com/downloads/connector/c/
3.4 Oracle、PostgreSql、sqlite我个人没有研究,网址就不给了哈;
3.5 MS Sql Server(odbc): odbc32.lib;odbccp32.lib;
注1:建议pthreads-win32用动态库, 静态库需要对pthreads-win32进行初始化,见我的另一篇文章:注2: pthreads-win32和MySql Connector/C不能同时用静态库,线程函数有冲突,我当时是这样。但将libzdb编译成静态库是,好像都可以用静态库,所以关于这点,请大家一起来验证吧。pthread-win32库编译及使用方法注意事项 - CruiseYoung的专栏 http://blog.csdn.net/fksec/article/details/41517953
注3:支持的5种数据库(MySql、Oracle、PostgreSql、sqlite、MS Sql Server), 如用zdb.c嵌入工程时同时只能支持一种,其他方式可同时支持这五种。
4 建msvc工程(这个不需要我详细写了吧)
4.1 libzdb工程,该工程是将libzdb编译成静态库的工程
4.2 libzdb_unity工程,该工程是将libzdb源代码嵌入到自己的工程中的示例,和资源(zdb.c 以及工程配置)
4.3 TestException、TestPool、TestSelect、TestUnit四个工程对应官方提供的4个测试文件。作用看名字就猜得到哈。
详细见代码。
4.4 添加头文件的访问路径:
4.4.1 “libzdb”头文件访问路径,
例如:....src;....srcnet;....srcutil;....srcdb;....srcexceptions;....; // 保证"src/net/URL.re"、"src/system/Time.re"能够访问到;....src;....srcnet;....srcutil;....srcdb;....srcexceptions;// 以上路径是保证各自目录下的头文件能够访问到,有人会问为什么不配置src/system的路径,那是因为程序中关于system目录下的头文件的引用都有system打头,所以不需要了注:以上路径是相对于各自工程的相对路径,请根据实际情况配置。
4.4.2 其它库头文件访问路径,这个我就不讲了哈,请根据实际情况配置。我的工程以MySql为例来讲解;
4.5 工程公共预定义(各预定宏作用请自己搜索,此处我就不详讲了哈):XKEYCHECK_H;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;
5 静态库成功编译的修改
注:修改之前请先阅读,以下博文:
C代码从GCC到MSVC的移植http://blog.csdn.net/jinzhuojun/article/details/7881049
5.1 将所有libzdb库中引用自定义头文件时采用
#include <...>
统一改为#include "..."
涉及文件:srcexceptionsassert.h srcexceptionsAssertException.h srcexceptionsMemoryException.h srcexceptionsSQLException.h
5.2 “__attribute__”不能识别
处理在msvc上 标识符“__attribute__”不能识别的问题,该关键字是GCC下扩展的特有关键字,不过clang下好像也能识别。由于在以下文件:srcsystemSystem.h srcutilStr.h srcexceptionsException.h srcdbConnection.h srcnetURL.h srcutilStringBuffer.h
前3个文件在文件srcConfig.h引入“标识符‘__attribute__’”,其中前2个文件通过#include "Str.h" #include "system/System.h"
引入第3个文件通过#include "SQLException.h"
间接引入“标识符‘__attribute__’”所以有关“__attribute__”的宏应该出现这3个文件之前。因此,srcConfig.h中的以下语句/* ---------------------------------------------------------- Build macros */ /* Mask out GCC __attribute__ extension for non- GCC/llvm-clang compilers. */ #if (! (defined(__GNUC__) || defined(__clang__))) #define __attribute__(x) #endif
应提前到引入所有libzdb库自定义头文件的前面。此处为了统一处理,我在srcConfig.h文件同级目录下创建srcMacros.h文件,将上述宏移到srcMacros.h文件中。并在srcConfig.h文件语句后添加#include "xconfig.h"
#include "Macros.h"
由于srcexceptionsassert.h中用到了__attribute__,因此我们在其实现文件srcexceptionsassert.c中的语句之前添加#include "assert.h"
如此添加方式,是与库引用头文件的风格保持一致。#include "Macros.h"
5.3 “inline”不能识别
处理在msvc上 标识符“inline”不能识别的问题
原因(Inline assembly is not supported on the ARM and x64 processors.)见:Inline Assembler http://msdn.microsoft.com/en-us/library/4ks26t93.aspx 预定义的宏 http://msdn.microsoft.com/zh-cn/library/b0084kay(v=vs.120).aspx
在srcMacros.h文件中定义以下宏#if defined(_MSC_VER) && !defined(inline) #define inline __inline #endif
5.4 __func__”不能识别
处理在msvc上 标识符“__func__”不能识别的问题在srcMacros.h文件中定义以下宏#if defined(_MSC_VER) && !defined(__func__) #define __func__ __FUNCTION__ #endif
5.5 未声明的标识符“int64_t”、“INT32_MIN”、“INT32_MAX”
解决 未声明的标识符“int64_t”、“INT32_MIN”、“INT32_MAX”: 按如下方法添加头文件#ifdef _WIN32 #include <stdint.h> #include <inttypes.h> #endif
5.6 解决函数“snprintf”未定义:
在srcMacros.h文件中定义以下宏#if defined(_MSC_VER) && !defined(snprintf) #define snprintf _snprintf #endif
5.7 解决函数“gmtime_r”未定义
该函数一定要注意,找msvc中,与其功能相同的函数为gmtime_s, 但其参数需要交换。在srcMacros.h文件中所以定义以下宏#if defined(_MSC_VER) && !defined(gmtime_r) #include <time.h> #define gmtime_r(a, b) gmtime_s((b), (a)) #endif
5.8 解决类型“suseconds_t”未声明的标识符:
在srcMacros.h文件中定义以下宏#if defined(_MSC_VER) && !defined(suseconds_t) #define suseconds_t long #endif
5.9 解决“select”、struct“timeval”未定义
在srcMacros.h文件中定义以下宏#if defined(_MSC_VER) #include <WinSock2.h> // struct timeval //#pragma comment(lib, "ws2_32.lib") // select(0, 0, 0, 0, &t); #endif #ifndef _WIN32 #include <sys/time.h> #include <sys/select.h> #endif
5.10 “gettimeofday”未定义
解决函数“gettimeofday”未定义: 该函数在windows上没有与其对应的函数,需要自己实现。int gettimeofday(struct timeval *tv, struct timezone *tz);因此,我们要定义struct timezone.将5.9和5.10合并处理,在srcMacros.h文件中添加:#if defined(_MSC_VER) #include <WinSock2.h> /* struct timeval */ //#pragma comment(lib, "ws2_32.lib") /* release need select(0, 0, 0, 0, &t); */ //#include <time.h> /* struct timezone */ struct timezone { int tz_minuteswest; /* minutes west of Greenwich */ int tz_dsttime; /* type of DST correction */ }; int gettimeofday(struct timeval *tv, struct timezone *tz); #endif
我们在srcsystem目录下创建其实现文件gettimeofday.c,并添加以下代码#include "Macros.h" #if defined(_MSC_VER) && !defined(gettimeofday) #include <time.h> /* _timezone, _daylight */ #include <WinSock2.h> /* timeval */ #include <windows.h> /* I've ommited this line. */ #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 #else #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL #endif //struct timezone //{ // int tz_minuteswest; /* minutes west of Greenwich */ // int tz_dsttime; /* type of DST correction */ //}; int gettimeofday(struct timeval *tv, struct timezone *tz) { // Define a structure to receive the current Windows filetime FILETIME ft; // Initialize the present time to 0 and the timezone to UTC unsigned __int64 tmpres = 0; static int tzflag = 0; if (NULL != tv) { GetSystemTimeAsFileTime(&ft); // The GetSystemTimeAsFileTime returns the number of 100 nanosecond // intervals since Jan 1, 1601 in a structure. Copy the high bits t // the 64 bit tmpres, shift it left by 32 then or in the low 32 bit tmpres |= ft.dwHighDateTime; tmpres <<= 32; tmpres |= ft.dwLowDateTime; // Convert to microseconds by dividing by 10 tmpres /= 10; // The Unix epoch starts on Jan 1 1970. Need to subtract the diffe // in seconds from Jan 1 1601. tmpres -= DELTA_EPOCH_IN_MICROSECS; // Finally change microseconds to seconds and place in the seconds // The modulus picks up the microseconds. tv->tv_sec = (long)(tmpres / 1000000UL); tv->tv_usec = (long)(tmpres % 1000000UL); } if (NULL != tz) { if (!tzflag) { _tzset(); tzflag++; } tz->tz_minuteswest = _timezone / 60; tz->tz_dsttime = _daylight; } return 0; } #endif
5.11 头文件找不到
关于在win32平台上,非win32平台头文件找不到的问题,我们采用分平台引用,即但当前系统为win32平台时引用其在win32平台对应的头文件。涉及:5.11.1 <sys/time.h>、<sys/select.h>
做如下修改srcsystemTime.c中,修改为#ifndef _WIN32 #include <sys/time.h> #include <sys/select.h> #endif
srcsystemTime.re中,修改为#ifndef _WIN32 #include <sys/time.h> #include <sys/select.h> #endif
以上两文件中对应的win32头文件,我们统一放到srcMacros.h文件中,即#if defined(_MSC_VER) #include <time.h> #include <WinSock2.h> //#pragma comment(lib, "ws2_32.lib") // select(0, 0, 0, 0, &t); #include <windows.h> //I've ommited this line. #endif
以上语句在5.10中已经合并处理,不单独添加。
5.11.2 <strings.h>
srcutilStr.c中,修改为#ifndef _WIN32 #include <strings.h> #endif // !_WIN32
5.12 不同平台pthread_t的定义不同引入问题的修改
由于pthreads-win32下的 pthread_t与posix的pthread_t的定义不同:posix下pthread_t的定义是:typedef unsigned long int pthread_t;
而pthread_win32定义是:/* * Generic handle type - intended to extend uniqueness beyond * that available with a simple pointer. It should scale for either * IA-32 or IA-64. */ typedef struct { void * p; /* Pointer to actual object */ unsigned int x; /* Extra information - reuse count etc */ } ptw32_handle_t; typedef ptw32_handle_t pthread_t;
见:d:commpthreadsincludepthread.h(根据实际情况查看)所以:srcdbConnectionPool.c文件中语句stopSweep = (P->doSweep && P->reaper);
应分平台处理,即将其改为:#ifndef _WIN32 stopSweep = (P->doSweep && P->reaper); #else stopSweep = (P->doSweep && P->reaper.p); #endif // !_WIN32
请参考博文:pthread_win32下的 pthread_t与posix的pthread_t的不同http://www.cnblogs.com/ayanmw/archive/2012/08/07/2626661.html
5.13 Time.c、URL.c文件的修改
由于srcsystemTime.c文件和srcnetURL.c与对应的文件srcsystemTime.re srcnetURL.re的代码行号有关,所以要做对应修改,每次编译前都要检查srcsystemTime.re srcnetURL.re的代码是否有有关行号变化的情况。有变化则需作对应修改。
5.14 release版本需引入的头文件
在实际编译过程中发现,在release时在某些文件中还需要引入其它头文件,涉及:srcsystemTime.c srcutilStringBuffer.c
中,添加#include "AssertException.h" // release need
5.14 解决VERSION未定义问题
在srcConfig.h文件中/** * Version, copyright and contact information */ #define ABOUT "libzdb/" VERSION " Copyright (C) Tildeslash Ltd. " LIBZDB_URL
语句前添加:/* Version number of package */ #define VERSION "3.1.0"
5.15 添加控制数据库开关
在srcConfig.h文件中在引用头文件语句结束后,添加,每次只能打开一个宏(由于#include "xconfig.h"文件中把以下宏给undef了,所以在工程属性中配置无效)。#define HAVE_LIBMYSQLCLIENT //#define HAVE_LIBPQ //#define HAVE_LIBSQLITE3 //#define HAVE_ORACLE //#define HAVE_SQLSERVER
5.16 消除宏"ERROR"重定义警告 (不强制)
在所有宏定义“ERROR”之前取消“ERROR”定义,即语句#define ERROR(e) do {*error = Str_dup(e); goto error;} while (0)之前添加语句#undef ERROR出现在:srcdbmysqlMysqlConnection.c srcdboracleOracleConnection.c srcdbpostgresqlPostgresqlConnection.c
5.17 测试文件中作如下修改
5.17.1 testpool.c中,修改为#ifndef _WIN32 #include <unistd.h> #endif
并添加#if defined(_MSC_VER) && !defined(sleep) #define sleep Sleep #endif
5.17.2 testunit.c中添加#ifdef _WIN32 #include <io.h> //open #endif
6 unity编译方式
为了能直接将libzdb代码引入自己的工程请作以下修改:
6.1 解决结构体对象定义“typedef struct T *T;”类问题(“-->”符号意为“更改为”)
6.1.1 Vector
#define T Vector_T后的struct T {};-->struct Vector_S {};#define T Vector_T 后的typedef struct T *T;-->typedef struct Vector_S *T;
6.1.2 StringBuffer
#define T StringBuffer_T后的struct T {};-->struct StringBuffer_S {};#define T StringBuffer_T后的typedef struct T *T;-->typedef struct StringBuffer_S *T;
6.1.3 Exception
Exception.h 中#define T Exception_T后的typedef struct T { const char *name; } T;
-->struct Exception_S { const char *name; } ;
然后将所有Exception_T改为Exception_S,
6.1.4 ConnectionDelegate
// #define T ConnectionDelegate_T后的struct T {};-->struct ConnectionDelegate_S {};#define T ConnectionDelegate_T后的typedef struct T *T;-->typedef struct ConnectionDelegate_S *T;
6.1.5 PreparedStatementDelegate
#define T PreparedStatementDelegate_T后的struct T {};-->struct PreparedStatementDelegate_S {};#define T PreparedStatementDelegate_T后的typedef struct T *T;-->typedef struct PreparedStatementDelegate_S *T;
6.1.6 ResultSetDelegate
#define T ResultSetDelegate_T后的struct T {};-->struct ResultSetDelegate_S {};#define T ResultSetDelegate_T后的typedef struct T *T;-->typedef struct ResultSetDelegate_S *T;
6.1.7 Cop
typedef struct Cop_T { } *Cop_T; -->typedef struct Cop_S { } *Cop_T;即将所有的struct Cop_T改为struct Cop_S
6.1.8 Pop
typedef struct Pop_T { } *Pop_T; -->typedef struct Pop_S { } *Pop_T;即将所有的struct Pop_T改为struct Pop_S
6.1.9 Rop
typedef struct Rop_T { } *Rop_T; -->typedef struct Rop_S { } *Rop_T;即将所有的struct Rop_T改为struct Rop_S
6.1.10 column
typedef struct column_t{ } *column_t; -->typedef struct column_s { } *column_t;即将所有的struct column_t改为struct column_s
6.1.11 param
typedef struct param_t { } *param_t; --> typedef struct param_s { } *param_t;即将所有的struct param_t改为struct param_s
6.2 风格统一
通过对源代码的阅读,发现_S(_s)都是结构体的定义,_T(_t)代表指针6.2.1 Exception_Frametypedef struct Exception_Frame Exception_Frame; struct Exception_Frame {};
-->typedef struct Exception_Frame_S Exception_Frame; struct Exception_Frame_S {};
将所有的struct Exception_Frame-->struct Exception_Frame_S6.2.2 UnlockNotificationtypedef struct UnlockNotification { int fired; Sem_T cond; Mutex_T mutex; } UnlockNotification_T;
-->struct UnlockNotification_S { int fired; Sem_T cond; Mutex_T mutex; };
将所有的UnlockNotification_T-->UnlockNotification_S
6.3 “struct”类型重定义 (不强制)
注:原因可以参见以下博文:visual studio 2008 提示 “函数xxx 已有主体” - lengshuangfei的专栏 http://blog.csdn.net/lengshuangfei/article/details/6027792
6.3.1 struct param_ssrcnetURL.re srcnetURL.c
中struct param_s和各数据库xxxPreparedStatement.c实现中的struct param_s定义重定义了,为了方便修改,我们将以上两个文件中的struct param_s定义更改为并将以上两文件中的所有param_s、param_t作相应更改。typedef struct param_url_s { char *name; char *value; struct param_url_s *next; } *param_url_t;
6.4 函数“xxx”已有主体 (不强制)
注:原因可以参见以下博文:visual studio 2008 提示 “函数xxx 已有主体” - lengshuangfei的专栏 http://blog.csdn.net/lengshuangfei/article/details/6027792
6.4.1 void _ensureCapacity()
srcdbmysqlMysqlResultSet.csrcutilVector.c原因同6.3.1,将srcutilVector.c中所有的_ensureCapacity()更改为_ensureCapacity_Vector;
6.4.2 _prepare()
srcutilStringBuffer.c和各数据库xxxConnection.c实现文件原因同6.3.1,将srcutilStringBuffer.c中所有的_prepare()更改为_prepare_StringBuffer;
6.4.3 _ctor()
srcutilsrcnetStringBuffer.csrcnetURL.re原因同6.3.1,将srcutilStringBuffer.c中所有的_ctor()更改为_ctor_StringBuffer;
7 关于libzdb_unity工程的说明
7.1 修改zdb.h原因:为了方便直接引用,并不需要在工程中libzdb其它头文件的引用路径(只在statci库中适用),所以将其内容改为如下内容7.2 在zdb.h同级目录添加文件zdb.c文件,其内容是对所有实现文件的链接,避免一个文件一个文件的添加 (此种方式,必须进行步骤6.3、6.4)。内容如下(顺序是msvc的编译顺序)/* Mask out __attribute__ extension for non- GCC/llvm-clang compilers. */ #if (! (defined(__GNUC__) || defined(__clang__))) #define __attribute__(x) #endif #if defined(_MSC_VER) && !defined(inline) #define inline __inline #endif #if defined(_MSC_VER) && !defined(__func__) #define __func__ __FUNCTION__ #endif /* libzdb API interfaces */ #include "exceptions/SQLException.h" #include "net/URL.h" #include "db/ResultSet.h" #include "db/PreparedStatement.h" #include "db/Connection.h" #include "db/ConnectionPool.h"
7.3 要将libzdb嵌入自己的工程,只需用将zdb.c添加到自己的工程中,头文件只需引用zdb.h文件即可;#include "./util/Vector.c" #include "./util/StringBuffer.c" #include "./util/Str.c" #include "./system/Time.c" #include "./system/System.c" #include "./system/Mem.c" #ifdef _MSC_VER #include "./system/gettimeofday.c" #endif #include "./net/URL.c" #include "./exceptions/Exception.c" #include "./exceptions/assert.c" #include "./db/ResultSet.c" #include "./db/PreparedStatement.c" #ifdef HAVE_LIBMYSQLCLIENT #include "./db/mysql/MysqlResultSet.c" #include "./db/mysql/MysqlPreparedStatement.c" #include "./db/mysql/MysqlConnection.c" #endif #ifdef HAVE_ORACLE #include "./db/oracle/OracleResultSet.c" #include "./db/oracle/OraclePreparedStatement.c" #include "./db/oracle/OracleConnection.c" #endif #ifdef HAVE_LIBPQ #include "./db/postgresql/PostgresqlResultSet.c" #include "./db/postgresql/PostgresqlPreparedStatement.c" #include "./db/postgresql/PostgresqlConnection.c" #endif #ifdef HAVE_LIBSQLITE3 #include "./db/sqlite/SQLiteResultSet.c" #include "./db/sqlite/SQLitePreparedStatement.c" #include "./db/sqlite/SQLiteConnection.c" #endif #ifdef HAVE_SQLSERVER #include "./db/sqlserver/SqlServerResultSet.c" #include "./db/sqlserver/SqlServerPreparedStatement.c" #include "./db/sqlserver/SqlServerConnection.c" #endif #include "./db/ConnectionPool.c" #include "./db/Connection.c"
否则,就将源文件(.c或.re)一个一个地加入工程, 此时不需要执行步骤6.3、6.4。
8 头文件提取
8.1 如果我们将libzdb编译成静态库(动态库目前没有提供,可以自己加),需要提供头文件,所以需要提供zdb.h文件及其涉及到的其它头文件,请从libzdb_msvc/src目录中按目录层级拷贝以下文件到libzdb_msvc/include,列表如下
8.2 修改相关头文件exceptions/SQLException.h exceptions/Exception.h//(由exceptions/SQLException.h引入) net/URL.h db/ResultSet.h db/PreparedStatement.h db/Connection.h db/ConnectionPool.h
在以下文件
中语句db/ResultSet.h db/PreparedStatement.h db/Connection.h
之前添加//<< Protected methods
在语句#if 0
之后添加//>> End Protected methods
见libzdb_msvcinclude#endif
最后
以上就是风中大叔为你收集整理的将libzdb移植到msvc(Visual Studio 2013)1 资料准备2 编译代码准备3 该库依赖其它库4 建msvc工程(这个不需要我详细写了吧)5 静态库成功编译的修改6 unity编译方式7 关于libzdb_unity工程的说明8 头文件提取的全部内容,希望文章能够帮你解决将libzdb移植到msvc(Visual Studio 2013)1 资料准备2 编译代码准备3 该库依赖其它库4 建msvc工程(这个不需要我详细写了吧)5 静态库成功编译的修改6 unity编译方式7 关于libzdb_unity工程的说明8 头文件提取所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复