最近更新于 2025-03-10 09:01
测试环境
- Windows 11 24H2 64位
- Visual Studio 2022(已安装使用 C++ 的桌面开发)
- SQLite 3.49.1
开发中使用动态库
这里是以已经编译好的动态库的方式使用 SQLite3。SQLite3 是开源的,且 Public Domain,直接把它的源码放进自己的项目里一起编译也是没有顾虑的,这样 SQLite3 的源码就成自己项目的一部分了。
准备 SQLite3 库文件
SQLite 官网下载地址:https://www.sqlite.org/download.html
下载合并版源文件和 Windows x64 版库文件
解压库文件包,将文件夹重命名为 sqlite
解压源文件包后,将里面的 .h 文件复制到上面库文件的 sqlite 文件夹中
打开 VS 的工具命令行 x64 Native Tools Command Prompt for VS 2022
切换到 sqlite 文件夹
执行命令导出 lib 文件
LIB /MACHINE:X64 /DEF:sqlite3.def
创建项目
这里就新建一个空项目
在项目上右键在文件资源管理器中打开文件夹
把上面配置好的 sqlite 文件夹复制进去
源文件上右键添加->新建项
新建一个 test.cpp 文件
在项目上右键属性
在C/C++->常规下,附加包含目录把sqlite目录添加进去
在链接器->常规下,附加库目录把sqlite目录添加进去
在链接器->输入下,附加依赖项添加sqlite3.lib
在调试里,环境中填入PATH=sqlite文件所在目录,比如我这里写PATH=D:\work\development\MFC\Project1\sqlite。
这一步是调试的时候保证程序可以链接到 sqlite3.dll 文件,如果要将最终构建的程序发布出去,要复制一份 sqlite3.dll 到构建的程序文件同目录下,或者添加到系统 PATH 变量目录中
测试
在前面创建的 test.cpp 中写入
注意 SQLite3 是一个 C 语言项目,在 C++ 中使用最好添加上 extern "C"
extern "C"
{
#include "sqlite3.h"
}
#include <iostream>
int main()
{
sqlite3* db; // 句柄
if (sqlite3_open("test.db", &db) != SQLITE_OK) // 打开数据库
{
std::cerr << "打开数据库失败!" << std::endl; // 错误信息
return 1;
}
else
{
std::cout << "打开数据库成功!" << std::endl;
}
sqlite3_close(db); // 关闭数据库
}
可以看到创建了一个 SQLite3 数据库文件
SQLite3 命令工具
下载
解压放置到某个固定路径
把这个路径添加到环境变量PATH中
查看版本
sqlite3 --version
Window 本地编码宽字符串和 UTF-8 窄字符串互相转换
Windows 下默认的编码不是 UTF-8,而是根据设置语言变化的,中文下就是 GBK,基于 Visual Studio 开发 Windows 应用的时候默认编码是 Unicode(UTF-16LE),在这种状态下默认使用的是宽字符串,而 SQLite3 在不指定编码的情况下默认使用 UTF-8,而且是窄字符串,所以如果是在基于 Visual Studio 开发 Windows 应用,还需要和 SQLite3 交互的话,很大可能需要进行转换(我的观点是不改动环境,而是让开发者写的东西适应默认环境,这样出错的可能性就小)。
使用下面代码注意手动释放返回值的字符串(delete[] 字符串指针),两段代码都是基于 Windows API,需要引用头文件 Windows.h
char* gbkToUtf8(const WCHAR* gbkStr)
{
// 获取宽字符字符串的长度
int wideCharLen = wcslen(gbkStr) + 1; // 包括结尾的 '\0'
if (wideCharLen <= 0)
{
return nullptr; // 如果字符串为空,直接返回 nullptr
}
// 获取需要的 UTF-8 编码字符串的长度(包括结尾的 '\0')
int utf8Len = WideCharToMultiByte(CP_UTF8, 0, gbkStr, -1, nullptr, 0, nullptr, nullptr);
if (utf8Len <= 0)
{
return nullptr; // 如果转换失败,返回 nullptr
}
// 分配内存用于存储 UTF-8 编码的字符串
char* utf8Str = new char[utf8Len];
// 执行转换
if (WideCharToMultiByte(CP_UTF8, 0, gbkStr, -1, utf8Str, utf8Len, nullptr, nullptr) == 0)
{
delete[] utf8Str; // 如果转换失败,释放已分配的内存
return nullptr;
}
return utf8Str; // 返回转换后的 UTF-8 字符串
}
WCHAR* utf8ToGbk(const char* utf8Str)
{
// 获取宽字符字符串的长度
int wideCharLen = MultiByteToWideChar(CP_UTF8, 0, utf8Str, -1, nullptr, 0);
if (wideCharLen <= 0)
{
return nullptr; // 如果转换失败,返回 nullptr
}
// 分配内存用于存储宽字符字符串
WCHAR* wideCharStr = new WCHAR[wideCharLen];
MultiByteToWideChar(CP_UTF8, 0, utf8Str, -1, wideCharStr, wideCharLen);
// 获取 GBK 编码字符串的长度
int gbkLen = WideCharToMultiByte(CP_ACP, 0, wideCharStr, -1, nullptr, 0, nullptr, nullptr);
if (gbkLen <= 0)
{
delete[] wideCharStr; // 如果转换失败,释放已分配的内存
return nullptr;
}
// 分配内存用于存储 GBK 编码的字符串
char* gbkStr = new char[gbkLen];
WideCharToMultiByte(CP_ACP, 0, wideCharStr, -1, gbkStr, gbkLen, nullptr, nullptr);
// 将 GBK 编码的字符串转换为宽字符字符串
int gbkWideLen = MultiByteToWideChar(CP_ACP, 0, gbkStr, -1, nullptr, 0);
if (gbkWideLen <= 0)
{
delete[] wideCharStr;
delete[] gbkStr; // 如果转换失败,释放已分配的内存
return nullptr;
}
WCHAR* gbkWideStr = new WCHAR[gbkWideLen];
MultiByteToWideChar(CP_ACP, 0, gbkStr, -1, gbkWideStr, gbkWideLen);
// 释放中间变量
delete[] wideCharStr;
delete[] gbkStr;
return gbkWideStr; // 返回转换后的宽字符字符串
}