windows下编译leveldb(动态库+静态库)
环境准备
1)下载cmake并安装
下载路径: https://cmake.org/download/
2)下载leveldb源码
git clone https://github.com/google/leveldb.git
3)下载googletest和benchmark,cmake编译时需要
# 进入leveldb源码路径下的third_party
cd leveldb/third_party# 下载googletest
git clone https://github.com/google/googletest.git# 下载benchmark
git clone https://github.com/google/benchmark.git
生成工程文件
1)进入leveldb源码目录,以管理员方式打开cmd.exe,执行
cmake CMakeLists.txt
生成工程文件如下所示:
静态库编译
配置
无需任何配置,使用visual studio打开工程文件leveldb.sln直接编译即可。
生成
如编译debug版本,编译完成后在源码根目录的Debug文件夹下会生成对应的静态库。
测试
#include <iostream>
#include "leveldb/db.h"
#include "leveldb/write_batch.h"
using namespace std;int main()
{leveldb::DB* dbptr = nullptr;leveldb::Options options;options.create_if_missing = true;// open leveldb::Status status = leveldb::DB::Open(options, "./leveldb.db", &dbptr);if (!status.ok()) {// 失败返回状态字符串cout << "Open db failed, status: " << status.ToString() << endl;return -1;}assert(nullptr != dbptr);cout << "Open db success" << endl;// putleveldb::WriteOptions putOptions;putOptions.sync = true;status = dbptr->Put(putOptions, "TEST1", "RESULT1");if (!status.ok()) {cout << "Put failed, status: " << status.ToString() << endl;return -1;}cout << "Put success" << endl;// write leveldb::WriteBatch writeBatch;writeBatch.Put("name", "lucas");writeBatch.Put("age", "12");writeBatch.Put("sex", "boy");status = dbptr->Write(leveldb::WriteOptions(), &writeBatch);if (!status.ok()) {cout << "Write failed, status: " << status.ToString() << endl;return -1;}cout << "Write success" << endl;// getleveldb::ReadOptions getOptions;std::string value;status = dbptr->Get(getOptions, "TEST1", &value);if (!status.ok()) {cout << "Get failed, status: " << status.ToString() << std::endl;return -1;}cout << "Get success, value: " << value << std::endl;// iterleveldb::Iterator* it = dbptr->NewIterator(leveldb::ReadOptions());if (!it) {cout << "NewIterator failed" << endl;return -1;}cout << "Iterator test start" << endl;it->SeekToFirst();while (it->Valid()) {leveldb::Slice sKey = it->key();leveldb::Slice sVal = it->value();cout << "key:" << sKey.ToString() << " value:" << sVal.ToString() << endl;it->Next();}cout << "Iterator test finish" << endl;if (it) {delete (it);it = nullptr;}// deletestatus = dbptr->Delete(putOptions, "TEST1");if (!status.ok()) {cout << "Delete failed, status: " << status.ToString() << endl;return -1;}cout << "Delete success, key: " << "TEST1" << endl;if (dbptr) {delete dbptr;dbptr = nullptr;}cout << "test finished" << endl;system("pause");return 0;
}
测试结果:
动态库编译
配置
1)修改位置1(配置属性——常规——配置类型):
2)修改位置2(配置属性——高级——目标文件扩展名):
3)修改位置3(配置属性——C/C++——预处理器,增加LEVELDB_SHARED_LIBRARY):
生成
如生成Debug版本,编译完成后在源码根目录的Debug文件夹下会生成对应的动态库。
测试
采用手动加载动态库,这样具有良好的向下兼容性。
#include <iostream>
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
#include "leveldb/c.h"
using namespace std;typedef leveldb_t* (*LevelDBOpen)(const leveldb_options_t*, const char*, char**);
typedef leveldb_options_t* (*LevelDBCreate)(void);
typedef leveldb_writeoptions_t* (*LevelDBWriteOptionsCreate)(void);
typedef leveldb_readoptions_t* (*LevelDBReadOptionsCreate)(void);
typedef void (*LevelDBReadOptionsDestroy)(leveldb_readoptions_t*);
typedef void (*LevelDBPut)(leveldb_t*, const leveldb_writeoptions_t*,const char*, size_t, const char*,size_t, char**);
typedef char* (*LevelDBGet)(leveldb_t*, const leveldb_readoptions_t*,const char*, size_t, size_t*, char**);
typedef void (*LevelDBWrite)(leveldb_t*,const leveldb_writeoptions_t*,leveldb_writebatch_t*, char**);
typedef void (*LevelDBDelete)(leveldb_t*,const leveldb_writeoptions_t*,const char*, size_t, char**);
typedef void (*LevelDBClose)(leveldb_t*);
typedef void (*LevelDBDestroy)(const leveldb_options_t*,const char*, char**);
typedef void (*LevelDBSetCreateIfMissing)(leveldb_options_t*, uint8_t);
typedef void (*LevelDBFree)(void*);
typedef leveldb_writebatch_t* (*LevelDBWriteBatchCreate)(void);
typedef void (*LevelDBWriteBatchDestroy)(leveldb_writebatch_t*);
typedef void (*LevelDBWriteBatchPut)(leveldb_writebatch_t*, const char*,size_t, const char*, size_t);int main()
{HMODULE handle = ::LoadLibrary(_T("./leveldb.dll"));if (!handle) {cout << "Load failed!" << endl;return -1;}cout << "Load success" << endl;// get funcLevelDBOpen func_open = (LevelDBOpen)GetProcAddress(handle, "leveldb_open");LevelDBCreate func_options_create = (LevelDBCreate)GetProcAddress(handle, "leveldb_options_create");LevelDBWriteOptionsCreate func_write_options_create =(LevelDBWriteOptionsCreate)GetProcAddress(handle, "leveldb_writeoptions_create");LevelDBReadOptionsCreate func_read_options_create =(LevelDBReadOptionsCreate)GetProcAddress(handle, "leveldb_readoptions_create");LevelDBReadOptionsDestroy func_read_options_destroy =(LevelDBReadOptionsDestroy)GetProcAddress(handle, "leveldb_readoptions_destroy");LevelDBPut func_put = (LevelDBPut)GetProcAddress(handle, "leveldb_put");LevelDBGet func_get = (LevelDBGet)GetProcAddress(handle, "leveldb_get");LevelDBWrite func_write =(LevelDBWrite)GetProcAddress(handle, "leveldb_write");LevelDBDelete func_delete =(LevelDBDelete)GetProcAddress(handle, "leveldb_delete");LevelDBClose func_close =(LevelDBClose)GetProcAddress(handle, "leveldb_close");LevelDBDestroy func_destroy =(LevelDBDestroy)GetProcAddress(handle, "leveldb_destroy_db");LevelDBSetCreateIfMissing func_options_set_create_if_missing =(LevelDBSetCreateIfMissing)GetProcAddress(handle, "leveldb_options_set_create_if_missing");LevelDBFree func_free = (LevelDBFree)GetProcAddress(handle, "leveldb_free");LevelDBWriteBatchCreate func_writebatch_create =(LevelDBWriteBatchCreate)GetProcAddress(handle, "leveldb_writebatch_create");LevelDBWriteBatchDestroy func_writebatch_destroy =(LevelDBWriteBatchDestroy)GetProcAddress(handle, "leveldb_writebatch_destroy");LevelDBWriteBatchPut func_writebatch_put =(LevelDBWriteBatchPut)GetProcAddress(handle, "leveldb_writebatch_put");if (nullptr == func_open|| nullptr == func_options_create || nullptr == func_write_options_create || nullptr == func_read_options_create || nullptr == func_read_options_destroy|| nullptr == func_put|| nullptr == func_get|| nullptr == func_delete|| nullptr == func_close|| nullptr == func_destroy|| nullptr == func_options_set_create_if_missing|| nullptr == func_free || nullptr == func_writebatch_create|| nullptr == func_writebatch_destroy|| nullptr == func_writebatch_put) {DWORD dw = GetLastError();cout << "Get func failed, err: " << dw << endl;return -1;}cout << "Open func success" << endl;// Openchar* err = nullptr;leveldb_options_t* options = nullptr;options = func_options_create();func_options_set_create_if_missing(options, 1);leveldb_t* db = func_open(options, "./leveldb.db", &err);if (nullptr != err) {cout << "Open failed, err: " << err << endl;return -1;}func_free(err);err = nullptr;cout << "Open success" << endl;// Putleveldb_writeoptions_t* woptions = nullptr;woptions = func_write_options_create();func_put(db, woptions, "key", 5, "value", 5, &err);if (nullptr != err) {cout << "Put failed, err: " << err << endl;return -1;}func_free(err);err = nullptr;cout << "Put success" << endl;leveldb_writebatch_t* batch = func_writebatch_create();func_writebatch_put(batch, "foo", 3, "a", 1);func_writebatch_put(batch, "bar", 3, "b", 1);func_writebatch_put(batch, "box", 3, "c", 1);func_write(db, woptions, batch, &err);if (nullptr != err) {cout << "Write failed, err: " << err << endl;return -1;}func_free(err);err = nullptr;func_writebatch_destroy(batch);cout << "Write success" << endl;// Readsize_t read_len = 0;leveldb_readoptions_t* roptions = func_read_options_create();char* read = func_get(db, roptions, "key", 5, &read_len, &err);if (nullptr != err) {cout << "Read failed!" << endl;return -1;}func_free(err);err = nullptr;func_read_options_destroy(roptions);cout << "Read success" << endl;// Deletefunc_delete(db, woptions, "key", 3, &err);if (nullptr != err) {cout << "Delete failed!" << endl;return -1;}func_free(err);err = nullptr;cout << "Delete success" << endl;// Closefunc_close(db);cout << "Close success" << endl;// Destroyfunc_destroy(options, "./leveldb.db", &err);if (nullptr != err) {cout << "Destroy failed!" << endl;return -1;}func_free(err);err = nullptr;cout << "Destroy success" << endl;FreeLibrary(handle);system("pause");return 0;
}
测试结果:
参考:
leveldb介绍:https://blog.csdn.net/joelcat/article/details/89240584
linux下安装leveldb:https://blog.csdn.net/www_dong/article/details/107307944
相关文章:

windows下编译leveldb(动态库+静态库)
环境准备 1)下载cmake并安装 下载路径: https://cmake.org/download/2)下载leveldb源码 git clone https://github.com/google/leveldb.git3)下载googletest和benchmark,cmake编译时需要 # 进入leveldb源码路径下的third_part…...
如何用76行代码写一个AI微信机器人......
本期博客主要介绍如何使用 微信SDK 和 AI聊天接口 ,实现 微信机器人功能。 准备 电脑需要安装Go环境,这个可以直接参考菜鸟教程:Go 语言环境安装,知道CSDN的同学基本能在半小时内装好吧…(可选)一个编译器…...

拿下域控后,我还是对大佬的操作念念不忘
历来攻防演练中,我都笃信一个道理——吃饱了才有力气干活。所以,在清晨的客户现场,当看到大佬满意地吃完了我带来的煎饺,我知道这一战,我们作为攻击队,基本已经拿下了。 虽然说的每一句话都带着一股醋味儿…...

实习-----Mybatis 框架
Mybatis 框架ORM持久化介绍 了解什么是“持久化”即把数据(如内存中的对象)保存的磁盘的某一文件中ORM概念ORM,即Object Relational Mapping,它是对象关系映射的简称。它的作用是在关系型数据库和对象之间作一个映射,是…...

【Linux】孤儿进程 | 环境变量 | 命令行参数 | 进程优先级
文章目录1. 孤儿进程2. 环境变量1. PATH环境变量证明ls是系统指令修改自己写的可执行程序对应路径2. env——查看系统环境变量3. 获取环境变量envpenvirongetenv 函数获取 (主流)4. 总结3 . 命令行参数理解命令行参数4. 进程优先级优先级与权限的区分为什么会有优先级ÿ…...

Matlab字符串相关操作-拼接、格式化
常见的有三种方法:向量拼接、strcat函数和sprintf函数1、向量拼接在matlab中字符串本质上也是一个向量,可以通过矩阵运算来实现字符串的拼接,这里随便输入两个字符串a1和b1,用矩阵形式进行拼接:a1 I love;b1 Matlab…...
死磕Spring系列,SpringBoot启动流程
参考文章:SpringBoot启动流程系列讲解 参考视频:SpringBoot启动流程 吐血推荐视频:史上最完整的Spring启动流程 超级好文:SpringBoot执行原理 参考文章:SpringBoot资源接口ResourceLoader和Resource学习 参考文章&…...
关于条件变量wait操作中锁的作用
condition_variable::wait的锁 在看C Concurrency in Action 6.2.3节的线程安全队列时,其对condition_variable的使用与常规用法有点不同,我对condition_variable::wait中锁的作用产生了疑惑:它究竟是保护的谁?于是找到了 C noti…...

JUC并发编程与源码分析笔记09-原子类操作之十八罗汉增强
基本类型原子类 AtomicInteger、AtomicBoolean、AtomicLong。 常用API: public final int get();// 获取当前的值 public final int getAndSet(int newValue);// 获取当前值,并设置新值 public final int getAndIncrement();// 获取当前的值࿰…...

含分布式电源的配电网日前两阶段优化调度模型(Matlab代码实现)
👨🎓个人主页:研学社的博客💥💥💞💞欢迎来到本博客❤️❤️💥💥🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密…...

FreeRTOS的Delay函数
两个Delay函数有两个延时函数vTaskDelay:至少等待指定个数的Tick Interrupt才能变为就绪态xTaskDelayUtil:等待到指定的绝对时刻,才能变为就绪态个人感觉这两个延时函数就是,比如一个我等3个小时,一个是我等到下午3点的…...

HCIA-HarmonyOS Application Developer——题目集1
题目1 1、一位开发人员在设计应用程序时,添加了一个Text组件和Button组件,开发样图如下所示。该开发者不能选择哪种布局方式来放置组件? A、StackLayout B、DependentLayout C、DirectionalLayout D、TableLayout 解析:(A&#…...

高性能 Message ToJavaBean 工具 【easy.server.mapper】
easy.server.mapper 介绍 后端开发中,消息转换常见问题 Map 中的数据 转换成实体Bean数组 中的数据 转换成实体BeanServet 中的 param 转换成实体Bean 以上的三个问题是最常见的消息转换困扰。 以Map 举例 常见做法是 手动转换 Map<String,Object> da…...

Web前端学习:三 - 练习
三六:风筝效果 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style type"text/css">*{margin: 0;padding: 0;}.d1{width: 200px;height: 200px;background: yellow;position…...

面试题:Android 中 Intent 采用了什么设计模式?
答案是采用了原型模式。原型模式的好处在于方便地拷贝某个实例的属性进行使用、又不会对原实例造成影响,其逻辑在于对 Cloneable 接口的实现。 话不多说看下 Intent 的关键源码: // frameworks/base/core/java/android/content/Intent.java public cla…...

Java数据类型与变量
个人主页:平行线也会相交 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【JavaSE_primary】 文章目录字面常量数据类型变量整型变量字节型变量浮点数变量双精度浮点数单精度浮点数字符型变量布尔型变量空常量nu…...

Python为CANoe工程添加/删除DBC文件
前面文章我们对于通过COM来实现打开CANoe、导入CANoe配置工程、导入执行文件、启动CANoe软件和执行脚本;但是这只能完成最基本的功能调用,在实际得到使用过程中,特别是各家在推的CI/CD以及平台化,仅仅是实现这些功能是完全不够用的;比如dbc的添加和删除,这是我们非常必要…...
不同的产品经理特征和需要的能力
产品经理是一个管家,需要和各方沟通推动产品各个决策进展。 每天早上看看线上用户数据、看下今天要安排任务,接着就是和各方开会讨论推动产品实现。每天穿插于与 UI、用户以及完成自己的 todolist 中循环。如果公司体制完善,还要和运营、数据…...
webpack之处理样式资源
处理样式资源 本章节我们学习使用 Webpack 如何处理 Css、Less、Sass、Scss、Styl 样式资源 #介绍 Webpack 本身是不能识别样式资源的,所以我们需要借助 Loader 来帮助 Webpack 解析样式资源 我们找 Loader 都应该去官方文档中找到对应的 Loader,然后…...

Golang 接口笔记
基本介绍接口是一个数据类型,可以定义一组方法,但都不需要实现。并且interface中不能包含任何变量。到某个自定义类型要使用的时候,再根据具体情况把这些方法实现出来语法type 接口名 interface {method1(参数列表) 返回值列表method2(参数列…...
OpenLayers 可视化之热力图
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 热力图(Heatmap)又叫热点图,是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...

算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

WebRTC调研
WebRTC是什么,为什么,如何使用 WebRTC有什么优势 WebRTC Architecture Amazon KVS WebRTC 其它厂商WebRTC 海康门禁WebRTC 海康门禁其他界面整理 威视通WebRTC 局域网 Google浏览器 Microsoft Edge 公网 RTSP RTMP NVR ONVIF SIP SRT WebRTC协…...
机器学习的数学基础:线性模型
线性模型 线性模型的基本形式为: f ( x ) ω T x b f\left(\boldsymbol{x}\right)\boldsymbol{\omega}^\text{T}\boldsymbol{x}b f(x)ωTxb 回归问题 利用最小二乘法,得到 ω \boldsymbol{\omega} ω和 b b b的参数估计$ \boldsymbol{\hat{\omega}}…...
MeanFlow:何凯明新作,单步去噪图像生成新SOTA
1.简介 这篇文章介绍了一种名为MeanFlow的新型生成模型框架,旨在通过单步生成过程高效地将先验分布转换为数据分布。文章的核心创新在于引入了平均速度的概念,这一概念的引入使得模型能够通过单次函数评估完成从先验分布到数据分布的转换,显…...