简介面向需要在 Visual Studio 2013 中集成 MySQL 数据库开发的 C 程序员这份资源给出了 Connector/C 在 Win32 与 x64 两种目标平台下的完整编译成果与配套示例。压缩包共 63 个文件、约 24.98MB核心包含 21 个头文件、20 个静态/导入库文件、9 个 DLL 运行库、3 个 PDB 调试符号以及 2 个 C 示例源文件其中 mysqlcppconn 与 libmysql 等库文件分为 release/debug 和 32/64 位版本可直接按需选用。示例工程 MysqlTest 展示了使用 sql::mysql::MySQL_Driver 创建连接、执行 SQL、遍历 ResultSet 并释放资源的常规流程配合 ReadMe 和工程配置能够帮助初学或迁移至 VS2013 的开发者快速验证依赖配置、规避编译链接陷阱。已有 512 人学习使用适合需要离线编译产物或想通过现成代码理解 Connector/C 调用方式的读者。1. 为什么非要在 VS2013 里从源码编译 Mysql Connector C/Cwin32 与 x64 两套库才是关键关键的坑在预编译包。老项目把 Visual Studio 2013 当工具链写死了从官网下载的 Connector/C 二进制库要么 MSVC 运行时版本对不上要么只给 x64 缺 win32真正链接进工程的时候接二连三报错。把 MySQL Connector C/C 的源码在 VS2013 下从头编译一遍生成 win32 和 win64 两套库文件所有依赖就都锁在自己的构建环境里换机器、换目录都不会再出幺蛾子。这份资源就是完整的编译流程和配套示例代码适合负责老产线维护、需要 C 程序连接 MySQL 的工程师以及还在用 VS2013 做课程设计、临时要用 MySQL 的学生。2. 编译前的依赖准备MSVC 兼容、Boost 版本与目标平台选型写这种编译文章最先要克服的执念是官方有预编译包为什么还要自己编答案是运行时兼容的老账。2.1 为什么要自己编译而不是用官方预编译包VS2013 对应的编译器版本是 MSVC 12.0它的标准库实现基本停在 C11 早期状态。MySQL 官方提供的 Connector/C 预编译二进制从 8.0 开始主要面向 MSVC 2015/2017 构建直接把我这种老环境排除。退一步说即便用旧版 1.1.x 的官方二进制也经常遇到 LNK2038 RuntimeLibrary 不匹配——对方用/MD编出来的库工程里用的是/MT链接器直接拒绝干活。判断一个预编译包能不能用我一般只看一个数字VS2013 里_MSC_VER是 1800下载页面标注的构建工具如果是 14.x 或 19.x分别对应 VS2015/2017就不用再浪费时间试了链接阶段必然给脸色。这也是为什么自己编译才是这条路上的正解源码在手构建工具链完全由 CMake 加 VS2013 控制输出的库和消费它的项目处在同一个运行时环境里。另一个隐藏原因是 API 的双轨制。Connector/C 有 Legacy API 和 X DevAPI 两条线8.x 的预编译包头文件大量使用新标准特性VS2013 的 STL 消化不了。与其绕开这些不如挑一个与老编译器匹配的源码版本编译期和运行期都省心。2.2 依赖版本配对CMake、Boost 与 MySQL 客户端库Connector/C 源码不是拿到手就能编它依赖三个外部组件CMake 负责生成 VS 工程Boost 提供锁与智能指针的内部实现MySQL 客户端库负责底层网络协议。下表是我在实际环境里反复试出来的稳定组合依赖版本建议说明CMake3.4 ~ 3.83.10 之后对 VS2013 generator 兼容性明显下降Boost1.58 或 1.59过高版本的头文件写法 VS2013 不支持MySQL 客户端库5.7 或 8.0 对应 libmysql.dll8.0 需注意认证插件兼容Connector/C 源码1.1.13 或 8.0.14 早期版1.1.x 编译最稳先说 CMake。VS2013 的 generator 名是Visual Studio 12 2013CMake 3.10 之后虽然还保留这个 generator但缓存处理逻辑变了偶尔会漏生成某些配置文件。我推荐固定 3.8既能识别-A Win32参数又不妥协。Boost 是坑最多的地方。连接器源码里的驱动实现依赖 Boost 的作用域锁和 shared_ptrCMake 变量WITH_BOOST必须指向包含boost/子目录的根路径。1.58/1.59 是 VS2013 编译窗口的黄金版本再新的 Boost 里一些头文件开始用新语法老编译器直接报错。MySQL 客户端库要留意服务器版本。用 5.7 的 libmysql.dll 连 8.0 服务器时默认认证插件 caching_sha2_password 会导致连接失败这是 MySQL 8.0 的默认行为需要把服务器用户改回 mysql_native_password 才能兼容旧客户端。这属于环境问题不是代码问题排查时最容易绕远路。2.3 win32 还是 x64位数一致性才是硬道理库的位数必须与最终可执行程序一致。x86 的 exe 只能用 win32 的 mysqlcppconn.dll 和 libmysql.dllx64 的 exe 反之。这不是玄学是 Windows 加载器的工作机制exe 启动时按自身位数寻找对应架构的 DLL匹配不上就直接报“不是有效的 Win32 应用程序”。很多做二次开发的公司交付物是 x86 的 ActiveX 控件就必须用 win32 库而有些上位机系统或数据处理服务是 x64 的就得配 x64 库。最稳妥的做法是编译前先定平台后面 CMake 生成和 VS 编译都按这个平台执行别编了两轮才发现位数不一致。另外32 位代码里常见的/arch:SSE2选项在 x64 下没有意义两个平台的工程配置应该分开管理不要共用一份 vcxproj 属性表。轻度不一致会在链接阶段报错重度不一致会在运行时闪退后者更难查。3. 动手编译CMake 生成 VS2013 工程与双平台构建准备就绪后开始编译。资源包里附带的 build 脚本就是把下面这些 CMake 参数封装成一次调用你手动执行一遍会更清楚每一步在做什么。3.1 CMake 参数逐个说明Generator、Boost、SSL 和 MySQL 目录假定源码解压到C:\work\mysql-connector-cpp-srcBoost 解压到C:\libs\boost_1_59_0MySQL 客户端装在C:\Program Files\MySQL\MySQL Server 5.7。先为 win32 构建建一个独立目录cd C:/work/mysql-connector-cpp-src mkdir build-win32 cd build-win32 cmake -G Visual Studio 12 2013 -A Win32 \ -DWITH_BOOSTC:/libs/boost_1_59_0 \ -DWITH_SSLdisabled \ -DMYSQL_DIRC:/Program Files/MySQL/MySQL Server 5.7 \ -DBUILD_STATICOFF \ -DBUILD_TESTINGOFF ..-G Visual Studio 12 2013是 CMake 识别 VS2013 的标准名称“12”是 VS 内部版本号“2013”是日历版本两个都不能写错。-A Win32指定目标平台64 位构建时改成-A x64。WITH_BOOST指向 boost 源码根路径CMake 会自行找到boost/version.hpp。WITH_SSLdisabled先关掉 OpenSSL 依赖避免引入第三方编译链业务需要加密连接时再单独开。MYSQL_DIR是客户端库安装根目录CMake 在里面查找 libmysql.lib 和 mysql.h。BUILD_STATICOFF决定输出动态库需要静态库的改成 ON。最后的..指向源码根路径。如果在 Windows cmd 里执行把行尾的\换成^就能写多行命令。CMake 版本低于 3.1 时不识别-A参数改用-G Visual Studio 12 2013 Win64也能生成 x64 工程这是老版本 CMake 的写法。生成完成后 build-win32 目录下会出现MYSQLCPPCONN.sln这就是 VS2013 的解决方案文件。注意这里建议把编译目录和源码目录分开不要直接在源码根目录跑 cmake。混在一起后再想生成另一平台工程清理起来非常痛苦我在这上面浪费过半小时。3.2 在 VS2013 里选择目标与配置静态库还是动态库打开解决方案在“解决方案资源管理器”里能看到多个项目。关键目标有三个mysqlcppconn动态库、mysqlcppconn-static静态库、mysqlcppconn_shared动态库别名。我一般只编动态库因为静态库会把依赖代码膨胀进业务 exe后续调试符号对不上反而麻烦。在“生成”菜单里打开配置管理器活动解决方案配置设为 Release活动解决方案平台设为 Win32。如果你习惯命令行也可以直接用 devenvC:/Program Files (x86)/Microsoft Visual Studio 12.0/Common7/IDE/devenv.com \ MYSQLCPPCONN.sln /Build Release|Win32编译过程大概 5 到 10 分钟中间会有若干 Boost 模板的警告只要不出现 error 就是正常的。结束后到build-win32\driver\Release目录找 mysqlcppconn.dll 和 mysqlcppconn.lib。注意 Debug 和 Release 不能混用 Debug 版库链接 Release 版 exe链接阶段报 LNK2038反过来也一样库的运行时配置与宿主工程必须统一。3.3 示例项目连接库配置附加包含目录与附加依赖项头文件和库文件都拿到了开始配使用方工程。在 VS2013 里新建一个 Win32 控制台应用打开项目属性依次配置C/C → 附加包含目录添加两行C:\work\mysql-connector-cpp-src\include和C:\work\mysql-connector-cpp-src\include\cppconn。第一行是给mysql_driver.h用的第二行是给cppconn/*.h这些派生头文件用的缺一个就会报找不到头文件。链接器 → 附加库目录添加编译产物目录C:\work\mysql-connector-cpp-src\build-win32\driver\Release。链接器 → 附加依赖项添加mysqlcppconn.lib和libmysql.lib。前者是连接器自身的导入库后者是 MySQL 客户端协议的导入库两个缺一不可。最后把mysqlcppconn.dll和libmysql.dll复制到 exe 的输出目录与 exe 同级。漏掉这一步程序启动会直接弹“无法启动此程序因为计算机中丢失 libmysql.dll”。DLL 的位数再强调一次Win32 工程放 32 位 DLLx64 工程放 64 位 DLL。拿反了Windows 加载器会提示“不是有效的 Win32 应用程序”处理过很多次这个问题的人才知道它不是病毒也不是缺文件就是位数对不上。注意改了项目属性后先正常编译一次确认生成了输出目录再把 DLL 放进去。顺序反了的话复制 DLL 时找不到目标目录又得翻一次车。4. 示例代码拆解连接、建表、查询与预编译语句库配好了跑一个能实际连接的示例。因为资源包里附带了一套完整示例代码我直接按它的主线拆开讲你拿去改起来会更顺。4.1 最小连接代码骨架驱动单例、连接字符串与资源释放在 VS2013 的示例项目里新建 main.cpp先写最小连接逻辑#include iostream #include memory #include mysql_driver.h #include mysql_connection.h #include cppconn/exception.h int main() { try { sql::mysql::MySQL_Driver* driver sql::mysql::get_mysql_driver_instance(); std::unique_ptrsql::Connection conn( driver-connect(tcp://127.0.0.1:3306, root, 123456)); conn-setSchema(test_db); std::cout connected, server version conn-getServerVersion() std::endl; } catch (sql::SQLException e) { std::cerr SQL error: e.what() , code e.getErrorCode() , state e.getSQLState() std::endl; return 1; } return 0; }get_mysql_driver_instance()返回的是库内部管理的单例指针不需要也不能 delete。driver-connect的第一个参数必须是tcp://IP:端口的完整写法漏了tcp://前缀驱动会把整串当成本地 socket 文件路径连接必然失败。unique_ptrsql::Connection保证任何路径下连接都会析构这在后续使用预编译语句时尤其重要因为连接不释放服务端会话就一直在。异常处理这块what()是错误描述getErrorCode()是 MySQL 错误码getSQLState()是 SQLSTATE 字符串。三个值一起打出来才能快速区分是网络问题、权限问题还是 SQL 语法问题。只看what()的话像“Access denied”和“Unknown database”容易混淆。4.2 建表与 DMLStatement 和 executeUpdate 的实际用法连接成功后用 Statement 执行不返回结果集的 SQL#include cppconn/statement.h std::unique_ptrsql::Statement stmt(conn-createStatement()); stmt-execute(CREATE TABLE IF NOT EXISTS t_user ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(64) NOT NULL, age INT));createStatement()创建语句句柄和连接对象相互独立用unique_ptr持有即可。execute适合 DDLDML 用executeUpdate它返回受影响行数int affected stmt-executeUpdate( INSERT INTO t_user(name, age) VALUES(lisi, 30)); std::cout affected rows: affected std::endl;executeUpdate返回的是实际被修改的行数0 不代表失败很可能是 WHERE 条件没有命中数据。判断语句是否成功要看有没有抛异常而不是看行数的大小。这一点和很多从 JDBC 转过来的习惯不一样容易误判。查询用executeQuery返回ResultSet。注意游标只支持向前遍历next()返回 false 表示没有下一行。getInt、getString的参数可以写列名也可以写列索引索引从 1 开始std::unique_ptrsql::ResultSet res( stmt-executeQuery(SELECT id, name, age FROM t_user)); while (res-next()) { std::cout res-getInt(id) \t res-getString(name) \t res-getInt(age) std::endl; }4.3 PreparedStatement 参数化防注入与批量执行的性能点带用户输入的场景必须走预编译语句。老 C 工程最爱拼接 SQL 字符串省事但既慢又有注入风险。Connector/C 的 PreparedStatement 写法如下#include cppconn/prepared_statement.h std::unique_ptrsql::PreparedStatement pstmt( conn-prepareStatement(INSERT INTO t_user(name, age) VALUES(?, ?))); pstmt-setString(1, wangwu); pstmt-setInt(2, 28); int inserted pstmt-executeUpdate(); std::cout inserted: inserted std::endl;参数下标从 1 开始与 ODBC 的习惯一致。setString对应 VARCHAR/CHARsetInt对应 INT。如果表字段是 BIGINT务必用setInt64否则服务端会因类型不匹配截断数值。setDateTime处理 DATETIME直接传YYYY-MM-DD HH:MM:SS格式的字符串即可。预编译语句 prepare 之后可以反复执行循环里改参数然后executeUpdate服务端只解析一次 SQL 模板批量 INSERT 时性能优势非常明显。注意循环里不要重新prepareStatement也不要新建 Statement那样就退化回普通 SQL 了。5. 避坑VS2013 编译 Connector/C 时最常翻车的五个问题编译和首次连接是最容易栽跟头的阶段。下面五个问题我基本都踩过每条按现象、原因、解决写清楚你遇到类似的直接对号入座。5.1 LNK2038 运行时库不匹配Debug/Release 与 /MT、/MD 的混用现象VS2013 链接阶段报错形如LNK2038: mismatch detected for RuntimeLibrary: value MD_DynamicRelease doesnt match value MT_StaticRelease in mysqlcppconn.lib。原因mysqlcppconn 库源码以 Release /MD编译而使用方工程把“代码生成 → 运行库”设成了“多线程 (/MT)”。两种运行时互不兼容链接器直接拒绝。这个问题在接手别人留下的老工程时特别常见属性页里可能还残留着上古配置。解决打开项目属性 → C/C → 代码生成 → 运行库Release 设为“多线程 DLL (/MD)”Debug 设为“多线程调试 DLL (/MDd)”。改完要重新编译整个依赖链因为 /MT 和 /MD 的切换会触发全量重编别指望增量编译。5.2 编 8.x 源码报 C2039VS2013 的 STL 卡在新特性上现象用 Connector/C 8.x 源码在 VS2013 编译报错C2039: xxx is not a member of std例如std::is_trivially_copyable找不到。原因8.x 内部使用了 VS2013 STL 尚未实现的新特性。VS2013 对 C11 的支持有明确边界一些模板元编程写法在老编译器里直接缺符号。解决如果非要用 8.x第一选择是降到 8.0.14 以前还在 VS2013 能编的版本第二选择是关掉相关编译宏。我一般直接退回 Connector/C 1.1.13Legacy API 接口完全一样业务代码几乎不用改编译体验却天差地别。5.3 运行时找不到 libmysql.dll复制了文件程序还是闪退现象程序在开发机编译运行一切正常拷到别的机器后启动弹窗提示缺少libmysql.dll。原因开发机上 MySQL 安装目录在 PATH 里系统能找到 libmysql.dll换一台干净的机器PATH 里没有而 mysqlcppconn.dll 内部依赖它启动加载链直接断掉。解决发布时将libmysql.dll、mysqlcppconn.dll、msvcp120.dll三个文件放进 exe 同目录。同时确认 DLL 位数与 exe 一致x64 的 exe 配 32 位 libmysql.dll加载时会报“不是有效的 Win32 应用”换机器后很容易出现这种怪现象检查顺序是位数优先再查缺失。5.4 CMake 找不到 BoostWITH_BOOST 路径看似对实则少了一层现象cmake 配置阶段输出Could NOT find Boost而路径明明指向了 boost 源码目录。原因Connector/C 的 CMakeLists 把WITH_BOOST当 BOOST_ROOT 用要求该目录下直接存在boost/version.hpp。如果路径指到了 boost 的include子目录或者指到了 boost 源码的父目录查找就失败。解决确保C:\libs\boost_1_59_0\boost\version.hpp存在WITH_BOOST指向C:\libs\boost_1_59_0。更保险的做法是在 cmake 前设置系统环境变量BOOST_ROOT两个都指向同一路径避免不同脚本读取不同变量。5.5 连 8.0 服务器报认证失败caching_sha2_password 与旧客户端不兼容现象程序连接 MySQL 8.0 提示Access denied for user rootlocalhost但用命令行客户端能正常登录。原因MySQL 8.0 默认新建用户使用 caching_sha2_password 认证插件旧版 libmysql 客户端只认识 mysql_native_password握手阶段插件协商失败。这跟用户名密码对不对无关是协议层面的不匹配。解决在服务器端把用户认证方式切回旧版ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 123456; FLUSH PRIVILEGES;ALTER USER同时重置了密码FLUSH PRIVILEGES刷新授权表。这个操作在测试环境很常见但不要在共享生产库上乱改先找 DBA 确认。还有一个排查技巧命令行能连而程序连不上先在程序里把用户名密码打出来核对再检查认证插件顺序别反。6. 进阶双平台产物验证与独立部署习惯编译完成只是起点最后这两件事做对了这份库才算真正落地。6.1 双平台跑一遍验证脚本在 VS2013 里把示例项目分别切成 Win32 和 x64 各编译一次跑在同一台机器上确认两个 exe 都能连上 127.0.0.1 的 MySQL。验证内容不用多按这个清单建表语句是否执行成功INSERT 返回行数是否为 1SELECT 能读出刚插入的数据停掉 MySQL 服务后程序能打印出异常而不是闪退验证通过的标准是同一个 main.cpp两套位数下编译零 warning、运行零崩溃。如果你在 x64 下看到一堆整型截断警告多半是int和size_t混用顺手把res-getInt换成res-getInt64并调整对应打印格式。中文乱码的问题也在这个阶段一起解决。连接建立后执行一次stmt-execute(SET NAMES utf8mb4)再查中文就不会出现问号。字符集问题看起来是库的锅实际上是连接会话缺了这条初始化语句。6.2 独立部署文件清单与一个发布习惯一份库要交给别的开发组或直接上生产机时最少需要以下文件文件说明mysqlcppconn.dll连接器动态库libmysql.dllMySQL 客户端网络库msvcp120.dllVS2013 的 C 运行库app.exe业务程序如果采用 mysqlcppconn-static.lib 静态链接就不用带 mysqlcppconn.dll但 libmysql.dll 依然需要连接器的 TCP 协议栈仍由它提供。msvcp120.dll 在装有 VC 运行库的环境里可以不重复放但放进同目录是最省心的做法能减少现场机器的环境差异。我后来把老设备程序的发布脚本改成自动拷贝这三个 DLL 到目标目录再也没人打电话问“为什么我的机器上跑不起来”。从那以后每次编译完第一件事是检查输出目录里的 DLL 位数用 dumpbin 看一眼machine (x86)还是machine (x64)确认与目标 exe 匹配才打包。希望帮到你——这个流程在 VS2013 上是死命令换了别的编译器版本记住“运行时一致、位数一致、路径一致”三条基本不会再翻车。本文还有配套的精品资源点击获取 SEO 优化官网定制响应式建站教育培训建站