• 分享封装好的异步Mysql动态的库(DyNetMysql.dll) + 项目源码


    在做C++项目时,经常会用到Mysql数据库,Mysql接口提供给我们的数据是相当原始的,如:字段名、字段类型,字段长度等等,一般情况我们都想一种更方便获得数据

    如:

    XXXStruct* pRecourdInfo = (const XXXStruct*)(mysql获得的数据指针);

    直接转换字段对应的结构来,这样能大大方便我们使用

    这个功能已经在我之前发表上一篇文章<<分享一直在维护简单实用高效的C++Socket框架Swa-server(开源+源码)>>中实现,现在是将它封装成为一个dll

    最近有点时间,就学习了dll相关知识,然后将封装成一个dll,这样方便使用及移植到其他项目。于是将swa-server中的mysql异步处理功能代码分离出来,创建一个DyNetMysql项目,设置为dll项目

    关于dll项目及导出不要这里讲述,园友自己百度查询(zf把谷歌封了真是服了)

    根据园友性格就先上代码(*_*)

    // TestDll.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include "../../DyNetServer/NetServer.h"
    #include "../../DyNetMysql/DbSession.h"
    #include "../../DyNetMysql/DbRecordSet.h"
    
    #include <iostream>
    using namespace std;
    
    NetServer*	gNetServer;
    IDbSession*	gDataBase;
    
    void OnNetMsgEnter( NetSocket& rSocket );
    void OnNetMsgExit( NetSocket& rSocket );
    void OnNetMsg( NetSocket& rSocket , NetMsgHead* pHead );
    
    #pragma pack(push,1)
    struct CharacterInfo
    {
    	int64 type_idx;
    	char nick[32];
    	int32 level;
    };
    #pragma pack(pop)
    
    void DBCallbase(void* pUser, const void* pMsg)
    {
    	const DbRecordSet* pRecordSet = static_cast<const DbRecordSet*>(pMsg);
    	for (int32 i = 0 ; i < pRecordSet->CountRecord();++i )
    	{
    		const CharacterInfo* pInfo = static_cast<const CharacterInfo*>(pRecordSet->GetRecordBuff(i));
    		printf("id:%ld nick:%s level:%d 
    ",pInfo->type_idx,pInfo->nick,pInfo->level);
    	}
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    
    	// 启动msyql
    	gDataBase = DbSessionMgr::Instance()->AddDatabase("127.0.0.1", "root", "root", "swa_data", false);
    	ASSERT(gDataBase);
    
    	// 初始化Scoket服务
    	gNetServer = NetServerMgr::Instance()->AddNetServer();
    	gNetServer->SetAddress("127.0.0.1", 4321);
    	gNetServer->SetHandler(OnNetMsgEnter, OnNetMsg, OnNetMsgExit);
    
    	// 启动Socket服务
    	gNetServer->Start();
    
    	gDataBase->ExecuteAsyncSQL("SELECT `type_idx`,`nick`,`level` FROM `character`",NULL,DBCallbase);
    	while (true)
    	{
    		Sleep(1);
    		NetServerMgr::Instance()->Update(0); //逻辑处理
    		DbSessionMgr::Instance()->Update(0); //SQL处理及回调
    	}
    	return 0;
    }
    
    void OnNetMsgEnter(NetSocket& rSocket)
    {
    	int a = 1;
    }
    
    void OnNetMsg(NetSocket& rSocket, NetMsgHead* pHead)
    {
    	int a = 1;
    }
    
    void OnNetMsgExit(NetSocket& rSocket)
    {
    	int a = 1;
    }
    

    这里启动创建一个Mysql连接对象,如果成功返回!null,然后可以异步执行sql及设置回调(可以不设置回调)

    上述代码运行效果图如下(为什么用printf,如果是字符放在第二以上显示为<null>,园友如果知道是什么原因,LZ感激不尽):

    其实实现将数据直接转结构体也不是很难,即每行给一个char buffer[65536],然后将mysql的字段内存拷贝进去,之后再转为结构体即可

    这里需要注意的,如果是char或varchar字段的,转出来要知道mysql是用什么字符编码,如果是utf-8则它byte最大长度为定义长度*3,本dynetmysql是按utf-8,且长度默认为字节长度,所以存储是中文时要注意,一个中文是用3个长度。

    相关类部分代码1:

        DbRecordSet&    m_rRecordSet;
        vector<DbField>    m_vecFields;
        char            m_arrRowBuff[65536]; // 每一行内容记录,每个字段记录它的开始位置即可,则一行记录最大为64k 
        uint32            m_nBuffBegin; // 已经使用的位置

    相关类部分代码2:

        switch (nType)
        {
        case FIELD_TYPE_TINY:
        {
            mI64Val = pszValue ? atol(pszValue) : 0;
            memcpy(&m_arrRowBuff[m_nBuffBegin], &mI64Val, 1);
            m_nBuffBegin += 1;
        }
            break;
        case FIELD_TYPE_SHORT:
        {
            mI64Val = pszValue ? atol(pszValue) : 0;
            memcpy(&m_arrRowBuff[m_nBuffBegin], &mI64Val, 2);
            m_nBuffBegin += 2;
        }
            break;
        case FIELD_TYPE_LONG:
        {
            mI64Val = pszValue ? atol(pszValue) : 0;
            memcpy(&m_arrRowBuff[m_nBuffBegin], &mI64Val, 4);
            m_nBuffBegin += 4;
        }
            break;
        case FIELD_TYPE_FLOAT:
        {
            mF64Val = pszValue ? atof(pszValue) : 0;
            memcpy(&m_arrRowBuff[m_nBuffBegin], &mF64Val, 4);
            m_nBuffBegin += 4;
        }
            break;
        case FIELD_TYPE_LONGLONG:
        {
            mI64Val = pszValue ? atol(pszValue) : 0;
            memcpy(&m_arrRowBuff[m_nBuffBegin], &mI64Val, 8);
            m_nBuffBegin += 8;
        }
            break;
        case FIELD_TYPE_DOUBLE:
        {
            mF64Val = pszValue ? atof(pszValue) : 0;
            memcpy(&m_arrRowBuff[m_nBuffBegin], &mF64Val, 8);
            m_nBuffBegin += 8;
        }
            break;
        case FIELD_TYPE_STRING:// char
        case FIELD_TYPE_VAR_STRING:// var_char
        {
            memcpy(&m_arrRowBuff[m_nBuffBegin], pszValue, nLen / 3); // mysql char 定义大小会按最大长底去计算长度,这里限制按字节大小去截断
            m_nBuffBegin += nLen / 3;
        }
            break;
        case MYSQL_TYPE_TINY_BLOB:
        case MYSQL_TYPE_MEDIUM_BLOB:
        case MYSQL_TYPE_LONG_BLOB:
        case MYSQL_TYPE_BLOB:
        {
            memcpy(&m_arrRowBuff[m_nBuffBegin], pszValue, nLen);
            m_nBuffBegin += nLen;
        }
            break;

    目前这个DyNetMysql.dll还不完善,如果是直接select 则可以创建结构体与它对应则可直接转结构体,如果是其它如update,delete乖等,则建议设置不使用回调或使用存储过程。

    测试代码中也用到了最近封装一个异步Socket的dll,如果大家感兴趣,请留言和推荐吧,我才会有动力跟园友一起分享!如果有问题,可以留言或qq296464231问我

    项目源码下载

  • 相关阅读:
    通过命令行配置samba服务
    新版python logging 封装,支持同时向console,file,socket输出
    python多进程管理DEMO
    注意tornado中的日志操作
    一个简单的python日志服务器
    NoVNC的使用、websockify以及VNC截图
    Oracle——distinct的用法
    C# Excel数据转化为Datatable
    C# winform 无API函数实现系统快捷键
    [转]C# WInForm 无框窗体移动
  • 原文地址:https://www.cnblogs.com/hellohuang/p/4452038.html
Copyright © 2020-2023  润新知