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(参数列…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...

《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...

三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...