概述:windows下编译libpq
🍡 注意1:PostgreSQL 从版本10之后就只有64位了。使用pqxx也不用考虑32位
使用版本说明:
PostGreSQL: 16.1
pqxx: 7.7.6
🍡 注意2: pqxx 使用的是 C++17
0x01 前言
what: The official C++ client API for PostgreSQL.
0x02 下载源码
源码仓库提供了windows下快速编译libpq的方法。但不好用,本人尝试但未能成功。
0x03 使用 cmake 编译 pqxx
编译
编译 pqxx 需要 PostGreSQL 的运行环境,因此需要下载二进制包才能编译成功。去 PostgreSQL 官网下载安装包或者二进制包都可以。
下载完成后,分两种情况,如果是下载的安装包,安装 postgresql 后直接用 cmake 编译就可以了,如果下载的是二进制文件,则需要配置cmake的变量如下所示,直接修改根目录的 CMakeLists.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 cmake_minimum_required (VERSION 3.8 )file (READ VERSION VER_FILE_CONTENT)string (STRIP ${VER_FILE_CONTENT} VER_FILE_CONTENT)project ( libpqxx VERSION ${VER_FILE_CONTENT} LANGUAGES CXX )set (PostgreSQL_ROOT "D:\\Documents\\postgresql\\postgresql-16.1-1-windows-x64-binaries\\pgsql" )if (NOT "${CMAKE_CXX_STANDARD}" ) set (CMAKE_CXX_STANDARD 17 )endif ()set (CMAKE_CXX_STANDARD_REQUIRED ON )set (CMAKE_CXX_EXTENSIONS OFF )set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR} /cmake)
然后就是使用 cmake
编译了,目前 VSCode 和 Visual Studio 都支持 CMake 文件的编译,直接编译即可。
这里使用 Visual Studio 编译后,会在 out 目录下生成lib文件,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 D:\Documents\A_Source\OpenSource\libpqxx\out >tree /F 卷 本地磁盘 的文件夹 PATH 列表 卷序列号为 724 D-690 E D:. ├─build │ └─x64-Debug │ │ .ninja_deps │ │ .ninja_log │ │ build.ninja │ │ CMakeCache.txt │ │ cmake_install.cmake │ │ CPackConfig.cmake │ │ CPackSourceConfig.cmake │ │ install_manifest.txt │ │ libpqxx-config-version .cmake │ │ libpqxx-config.cmake │ │ libpqxx-targets.cmake │ │ libpqxx.pc │ │ VSInheritEnvironments.txt │ │ │ ├─.cmake │ │ └─api │ │ └─v1 │ │ ├─query │ │ │ └─client-MicrosoftVS │ │ │ query.json │ │ │ │ │ └─reply │ │ cache -v2-4 c1f3ae5d14ffd09e2dd.json │ │ cmakeFiles-v1-6 f2def4807820d15719b.json │ │ codemodel-v2-8933 aef952d7508a3af3.json │ │ directory-.-Debug -6 b54e12c0d4bd01edfca.json │ │ directory-include -Debug -ba96d77232f254970ce6.json │ │ directory-src-Debug -5 d1cc30954eb9bce3508.json │ │ directory-test-Debug -f18be1977b403cfd1a50.json │ │ index -2023 -11 -16 T09-03 -01 -0309. json │ │ target-pqxx-Debug -08 c4b9d672ef282e41c8.json │ │ target-runner-Debug -b625a8b78dd4666c4f11.json │ │ toolchains-v1-3 b995f712f6d6e9a85c1.json │ │ │ ├─CMakeFiles │ │ │ cmake.check_cache │ │ │ CMakeConfigureLog.yaml │ │ │ rules.ninja │ │ │ TargetDirectories.txt │ │ │ │ │ ├─3.26 .4 -msvc4 │ │ │ │ CMakeCXXCompiler.cmake │ │ │ │ CMakeDetermineCompilerABI_CXX.bin │ │ │ │ CMakeRCCompiler.cmake │ │ │ │ CMakeSystem.cmake │ │ │ │ │ │ │ └─CompilerIdCXX │ │ │ │ CMakeCXXCompilerId.cpp │ │ │ │ CMakeCXXCompilerId.exe │ │ │ │ CMakeCXXCompilerId.obj │ │ │ │ │ │ │ └─tmp │ │ ├─CMakeTmp │ │ ├─Export │ │ │ └─d6b66e93f8212dd1f00debf9f6654819 │ │ │ libpqxx-targets-debug .cmake │ │ │ libpqxx-targets.cmake │ │ │ │ │ ├─pkgRedirects │ │ └─ShowIncludes │ │ foo.h │ │ main.c │ │ main.obj │ │ │ ├─include │ │ │ cmake_install.cmake │ │ │ │ │ ├─CMakeFiles │ │ └─pqxx │ │ config-internal -compiler.h │ │ config-internal -libpq.h │ │ config-public -compiler.h │ │ config_cmake.h.in │ │ │ ├─src │ │ │ cmake_install.cmake │ │ │ pqxx.lib │ │ │ │ │ └─CMakeFiles │ │ └─pqxx.dir │ │ array .cxx.obj │ │ binarystring.cxx.obj │ │ blob.cxx.obj │ │ connection .cxx.obj │ │ cursor .cxx.obj │ │ encodings.cxx.obj │ │ errorhandler.cxx.obj │ │ except .cxx.obj │ │ field.cxx.obj │ │ largeobject.cxx.obj │ │ notification.cxx.obj │ │ params.cxx.obj │ │ pipeline.cxx.obj │ │ pqxx.pdb │ │ result.cxx.obj │ │ robusttransaction.cxx.obj │ │ row .cxx.obj │ │ sql_cursor.cxx.obj │ │ strconv.cxx.obj │ │ stream_from.cxx.obj │ │ stream_to.cxx.obj │ │ subtransaction.cxx.obj │ │ time .cxx.obj │ │ transaction .cxx.obj │ │ transaction_base.cxx.obj │ │ util.cxx.obj │ │ version .cxx.obj │ │ wait.cxx.obj │ │ │ ├─test │ │ │ cmake_install.cmake │ │ │ CTestTestfile.cmake │ │ │ runner.exe │ │ │ runner.ilk │ │ │ runner.pdb │ │ │ │ │ └─CMakeFiles │ │ └─runner.dir │ │ │ embed.manifest │ │ │ intermediate.manifest │ │ │ manifest.rc │ │ │ manifest.res │ │ │ runner.cxx.obj │ │ │ test00.cxx.obj │ │ │ test01.cxx.obj │ │ │ test02.cxx.obj │ │ │ test04.cxx.obj │ │ │ test07.cxx.obj │ │ │ test10.cxx.obj │ │ │ test11.cxx.obj │ │ │ test13.cxx.obj │ │ │ test14.cxx.obj │ │ │ test16.cxx.obj │ │ │ test17.cxx.obj │ │ │ test18.cxx.obj │ │ │ test20.cxx.obj │ │ │ test21.cxx.obj │ │ │ test26.cxx.obj │ │ │ test29.cxx.obj │ │ │ test30.cxx.obj │ │ │ test32.cxx.obj │ │ │ test37.cxx.obj │ │ │ test39.cxx.obj │ │ │ test46.cxx.obj │ │ │ test56.cxx.obj │ │ │ test60.cxx.obj │ │ │ test61.cxx.obj │ │ │ test62.cxx.obj │ │ │ test69.cxx.obj │ │ │ test70.cxx.obj │ │ │ test71.cxx.obj │ │ │ test72.cxx.obj │ │ │ test74.cxx.obj │ │ │ test75.cxx.obj │ │ │ test76.cxx.obj │ │ │ test77.cxx.obj │ │ │ test78.cxx.obj │ │ │ test79.cxx.obj │ │ │ test82.cxx.obj │ │ │ test84.cxx.obj │ │ │ test87.cxx.obj │ │ │ test88.cxx.obj │ │ │ test89.cxx.obj │ │ │ test90.cxx.obj │ │ │ vc140.pdb │ │ │ │ │ └─unit │ │ test_array.cxx.obj │ │ test_binarystring.cxx.obj │ │ test_blob.cxx.obj │ │ test_cancel_query.cxx.obj │ │ test_column.cxx.obj │ │ test_composite.cxx.obj │ │ test_connection.cxx.obj │ │ test_cursor.cxx.obj │ │ test_encodings.cxx.obj │ │ test_errorhandler.cxx.obj │ │ test_error_verbosity.cxx.obj │ │ test_escape.cxx.obj │ │ test_exceptions.cxx.obj │ │ test_field.cxx.obj │ │ test_float.cxx.obj │ │ test_largeobject.cxx.obj │ │ test_nonblocking_connect.cxx.obj │ │ test_notification.cxx.obj │ │ test_pipeline.cxx.obj │ │ test_prepared_statement.cxx.obj │ │ test_range.cxx.obj │ │ test_read_transaction.cxx.obj │ │ test_result_iteration.cxx.obj │ │ test_result_slicing.cxx.obj │ │ test_row.cxx.obj │ │ test_separated_list.cxx.obj │ │ test_simultaneous_transactions.cxx.obj │ │ test_sql_cursor.cxx.obj │ │ test_stateless_cursor.cxx.obj │ │ test_strconv.cxx.obj │ │ test_stream_from.cxx.obj │ │ test_stream_to.cxx.obj │ │ test_string_conversion.cxx.obj │ │ test_subtransaction.cxx.obj │ │ test_test_helpers.cxx.obj │ │ test_thread_safety_model.cxx.obj │ │ test_time.cxx.obj │ │ test_transaction.cxx.obj │ │ test_transaction_base.cxx.obj │ │ test_transaction_focus.cxx.obj │ │ test_transactor.cxx.obj │ │ test_type_name.cxx.obj │ │ test_zview.cxx.obj │ │ │ └─Testing │ └─Temporary │ LastTest.log │ └─install └─x64-Debug ├─include │ └─pqxx │ │ array │ │ array .hxx │ │ binarystring │ │ binarystring.hxx │ │ blob │ │ blob.hxx │ │ composite │ │ composite.hxx │ │ config-public -compiler.h │ │ connection │ │ connection .hxx │ │ cursor │ │ cursor .hxx │ │ dbtransaction │ │ dbtransaction.hxx │ │ errorhandler │ │ errorhandler.hxx │ │ except │ │ except .hxx │ │ field │ │ field.hxx │ │ isolation │ │ isolation .hxx │ │ largeobject │ │ largeobject.hxx │ │ nontransaction │ │ nontransaction.hxx │ │ notification │ │ notification.hxx │ │ params │ │ params.hxx │ │ pipeline │ │ pipeline.hxx │ │ pqxx │ │ prepared_statement │ │ prepared_statement.hxx │ │ range │ │ range.hxx │ │ result │ │ result.hxx │ │ robusttransaction │ │ robusttransaction.hxx │ │ row │ │ row .hxx │ │ separated_list │ │ separated_list.hxx │ │ strconv │ │ strconv.hxx │ │ stream_from │ │ stream_from.hxx │ │ stream_to │ │ stream_to.hxx │ │ subtransaction │ │ subtransaction.hxx │ │ time │ │ time .hxx │ │ transaction │ │ transaction .hxx │ │ transaction_base │ │ transaction_base.hxx │ │ transaction_focus │ │ transaction_focus.hxx │ │ transactor │ │ transactor.hxx │ │ types │ │ types .hxx │ │ util │ │ util.hxx │ │ version │ │ version .hxx │ │ zview │ │ zview.hxx │ │ │ └─internal │ │ array -composite.hxx │ │ callgate.hxx │ │ concat.hxx │ │ conversions.hxx │ │ encodings.hxx │ │ encoding_group.hxx │ │ header -post.hxx │ │ header -pre.hxx │ │ ignore-deprecated-post.hxx │ │ ignore-deprecated-pre.hxx │ │ libpq-forward.hxx │ │ result_iter.hxx │ │ result_iterator.hxx │ │ sql_cursor.hxx │ │ statement_parameters.hxx │ │ stream_iterator.hxx │ │ wait.hxx │ │ │ └─gates │ connection -errorhandler.hxx │ connection -largeobject.hxx │ connection -notification_receiver.hxx │ connection -pipeline.hxx │ connection -sql_cursor.hxx │ connection -stream_from.hxx │ connection -stream_to.hxx │ connection -transaction .hxx │ errorhandler-connection .hxx │ icursorstream-icursor_iterator.hxx │ icursor_iterator-icursorstream.hxx │ result-connection .hxx │ result-creation.hxx │ result-pipeline.hxx │ result-sql_cursor.hxx │ transaction -sql_cursor.hxx │ transaction -transaction_focus.hxx │ ├─lib │ │ pqxx.lib │ │ │ ├─cmake │ │ └─libpqxx │ │ libpqxx-config-version .cmake │ │ libpqxx-config.cmake │ │ libpqxx-targets-debug .cmake │ │ libpqxx-targets.cmake │ │ │ └─pkgconfig │ libpqxx.pc │ └─share └─doc └─libpqxx accessing-results.md binary-data.md datatypes.md escaping.md getting-started.md mainpage.md parameters.md performance.md prepared -statement .md streams.md thread-safety.md
⚠ 然后就可以编代码使用 pqxx.lib 了。除此之外,在编译项目时还需要添加 libpq.lib.
除此之外可以看到以下两个目录,这两个目录待会要引入到 VS 工程中:
使用
以下代码可直接使用,自测是没问题的。
如果有编译报错 C4996: '_Header_ciso646'
,关闭 SDL检查 再编译试试。
另外补充一点,编译的PE文件运行时依赖很多dll,包括但不限于 libpq.dll、libssl 等,可以选择部署到另外一台机器上,同时部署 C++ 运行时文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 #include <iostream> #include <windows.h> #include <pqxx/pqxx> #include <pqxx/transaction> int main (int argc, char * argv[]) { if (argc < 3 ) { printf ("Usage:\n %s <username> <password>" , argv[0 ]); exit (-1 ); } char conn[MAX_PATH]; sprintf (conn, "postgresql://%s:%s@localhost/postgres" , argv[1 ], argv[2 ]); try { pqxx::connection c{ conn }; pqxx::work txn{ c }; pqxx::result res = txn.exec ("SELECT * FROM pg_authid" ); for (int i = 0 ; i < res.size (); i++) { for (int j = 0 ; j < res[i].size (); j++) std::cout << "" << res[i].at (j) << '\t' ; std::cout << '\n' ; } } catch (std::bad_alloc const &) { std::cerr << "Out of memory!" << std::endl; } catch (pqxx::sql_error const & e) { std::cerr << "SQL error: " << e.what () << std::endl << "Query was: " << e.query () << std::endl; } catch (std::exception const & e) { std::cerr << "Exception: " << e.what () << std::endl; } catch (...) { std::cerr << "Unknown exception" << std::endl; } }
在安装postgresql的机器上输出如下所示: