diff --git a/.gitignore b/.gitignore index dfc1989d..a5f67b3b 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,9 @@ xcuserdata *.xcscmblueprint *.xcscheme +#python +venv + ## OS X .DS_Store diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..744b1c91 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "POSIX/Python/pybind11"] + path = POSIX/Python/pybind11 + url = https://github.com/pybind/pybind11.git diff --git a/POSIX/Python/CMakeLists.txt b/POSIX/Python/CMakeLists.txt new file mode 100644 index 00000000..bbbc6916 --- /dev/null +++ b/POSIX/Python/CMakeLists.txt @@ -0,0 +1,59 @@ +# +# Tencent is pleased to support the open source community by making +# MMKV available. +# +# Copyright (C) 2020 THL A29 Limited, a Tencent company. +# All rights reserved. +# +# Licensed under the BSD 3-Clause License (the "License"); you may not use +# this file except in compliance with the License. You may obtain a copy of +# the License at +# +# https://opensource.org/licenses/BSD-3-Clause +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# Sets the minimum version of CMake required to build the native library. + +cmake_minimum_required(VERSION 3.8.0) + +project(mmkv_python) + +IF(APPLE) + add_compile_definitions(FORCE_POSIX) +ENDIF() + +set(PYBIND11_CPP_STANDARD -std=c++1z) + +add_subdirectory(../../Core Core) +add_subdirectory(pybind11) + + +pybind11_add_module( # Sets the name of the library. + mmkv + + # Sets the library as a python module library. + MODULE + + # Provides a relative path to your source file(s). + libmmkv_python.cpp + ) + +target_include_directories(mmkv PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}) + +set_target_properties(mmkv PROPERTIES + CXX_STANDARD 17 + CXX_EXTENSIONS OFF + ) + +target_link_libraries( # Specifies the target library. + mmkv PRIVATE + core + pthread + ) diff --git a/POSIX/Python/libmmkv_python.cpp b/POSIX/Python/libmmkv_python.cpp new file mode 100644 index 00000000..21002ffa --- /dev/null +++ b/POSIX/Python/libmmkv_python.cpp @@ -0,0 +1,128 @@ +/* + * Tencent is pleased to support the open source community by making + * MMKV available. + * + * Copyright (C) 2020 THL A29 Limited, a Tencent company. + * All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use + * this file except in compliance with the License. You may obtain a copy of + * the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MMKV.h" +#include + +using namespace mmkv; +using namespace std; +namespace py = pybind11; + +static MMBuffer pyBytes2MMBuffer(const py::bytes &bytes) { + char *buffer = nullptr; + ssize_t length = 0; + if (PYBIND11_BYTES_AS_STRING_AND_SIZE(bytes.ptr(), &buffer, &length) == 0) { + return MMBuffer(buffer, length, MMBufferNoCopy); + } + return MMBuffer(0); +} + +PYBIND11_MODULE(mmkv, m) { + m.doc() = "An efficient, small mobile key-value storage framework developed by WeChat Team."; + + py::enum_(m, "MMKVMode") + .value("SingleProcess", MMKVMode::MMKV_SINGLE_PROCESS) + .value("MultiProcess", MMKVMode::MMKV_MULTI_PROCESS) + .export_values(); + + py::enum_(m, "MMKVLogLevel") + .value("LogNone", MMKVLogLevel::MMKVLogNone) + .value("LogDebug", MMKVLogLevel::MMKVLogDebug) + .value("LogInfo", MMKVLogLevel::MMKVLogInfo) + .value("LogWarning", MMKVLogLevel::MMKVLogWarning) + .value("LogError", MMKVLogLevel::MMKVLogError) + .export_values(); + + py::class_> clsMMKV(m, "MMKV"); + // .def(py::init(&MMKV::mmkvWithID), // TODO: not working + // py::arg("mmapID"), + // py::arg("mode") = MMKV_SINGLE_PROCESS, + // py::arg("cryptKey") = (string*) nullptr, + // py::arg("rootDir") = (string*) nullptr) + clsMMKV.def(py::init([](const string &mmapID, MMKVMode mode, const string &cryptKey, const string &rootDir) { + string *cryptKeyPtr = (cryptKey.length() > 0) ? (string *) &cryptKey : nullptr; + string *rootDirPtr = (rootDir.length() > 0) ? (string *) &rootDir : nullptr; + return MMKV::mmkvWithID(mmapID, mode, cryptKeyPtr, rootDirPtr); + }), + py::arg("mmapID"), py::arg("mode") = MMKV_SINGLE_PROCESS, py::arg("cryptKey") = string(), + py::arg("rootDir") = string()); + + clsMMKV.def_static("initializeMMKV", &MMKV::initializeMMKV, py::arg("rootDir"), py::arg("logLevel") = MMKVLogNone); + + clsMMKV.def_static( + "defaultMMKV", + [](MMKVMode mode, const string &cryptKey) { + string *cryptKeyPtr = (cryptKey.length() > 0) ? (string *) &cryptKey : nullptr; + return MMKV::defaultMMKV(mode, cryptKeyPtr); + }, + py::arg("mode") = MMKV_SINGLE_PROCESS, py::arg("cryptKey") = string()); + + clsMMKV.def("mmapID", &MMKV::mmapID); + clsMMKV.def_readonly("isInterProcess", &MMKV::m_isInterProcess); + + clsMMKV.def("cryptKey", &MMKV::cryptKey); + clsMMKV.def("reKey", &MMKV::reKey, py::arg("newCryptKey")); + clsMMKV.def("checkReSetCryptKey", &MMKV::checkReSetCryptKey, py::arg("newCryptKey")); + + // TODO: Doesn't work, why? + // clsMMKV.def("set", py::overload_cast(&MMKV::set), py::arg("value"), py::arg("key")); + clsMMKV.def("setBool", (bool (MMKV::*)(bool, const string &))(&MMKV::set), py::arg("value"), py::arg("key")); + clsMMKV.def("set", (bool (MMKV::*)(int32_t, const string &))(&MMKV::set), py::arg("value"), py::arg("key")); + clsMMKV.def("set", (bool (MMKV::*)(uint32_t, const string &))(&MMKV::set), py::arg("value"), py::arg("key")); + clsMMKV.def("set", (bool (MMKV::*)(int64_t, const string &))(&MMKV::set), py::arg("value"), py::arg("key")); + clsMMKV.def("set", (bool (MMKV::*)(uint64_t, const string &))(&MMKV::set), py::arg("value"), py::arg("key")); + clsMMKV.def("set", (bool (MMKV::*)(float, const string &))(&MMKV::set), py::arg("value"), py::arg("key")); + clsMMKV.def("set", (bool (MMKV::*)(double, const string &))(&MMKV::set), py::arg("value"), py::arg("key")); + //clsMMKV.def("set", (bool (MMKV::*)(const char*, const string&))(&MMKV::set), py::arg("value"), py::arg("key")); + clsMMKV.def("set", (bool (MMKV::*)(const string &, const string &))(&MMKV::set), py::arg("value"), py::arg("key")); +#if PY_MAJOR_VERSION >= 3 + clsMMKV.def( + "set", [](MMKV &kv, const py::bytes &value, const string &key) { return kv.set(pyBytes2MMBuffer(value), key); }, + py::arg("value"), py::arg("key")); +#endif + + clsMMKV.def("getBool", &MMKV::getBool, py::arg("key"), py::arg("defaultValue") = false); + clsMMKV.def("getInt", &MMKV::getInt32, py::arg("key"), py::arg("defaultValue") = 0); + clsMMKV.def("getUInt", &MMKV::getUInt32, py::arg("key"), py::arg("defaultValue") = 0); + clsMMKV.def("getLongInt", &MMKV::getInt64, py::arg("key"), py::arg("defaultValue") = 0); + clsMMKV.def("getLongUInt", &MMKV::getUInt64, py::arg("key"), py::arg("defaultValue") = 0); + clsMMKV.def("getFloat", &MMKV::getFloat, py::arg("key"), py::arg("defaultValue") = 0); + clsMMKV.def("getDouble", &MMKV::getDouble, py::arg("key"), py::arg("defaultValue") = 0); + clsMMKV.def( + "getStr", + [](MMKV &kv, const string &key, const string &defaultValue) { + string result; + if (kv.getString(key, result)) { + return result; + } + return defaultValue; + }, + py::arg("key"), py::arg("defaultValue") = string()); + clsMMKV.def( + "getBytes", + [](MMKV &kv, const string &key, const py::bytes &defaultValue) { + MMBuffer result = kv.getBytes(key); + if (result.length() > 0) { + return py::bytes((const char *) result.getPtr(), result.length()); + } + return defaultValue; + }, + py::arg("key"), py::arg("defaultValue") = py::bytes()); +} diff --git a/POSIX/Python/pybind11 b/POSIX/Python/pybind11 new file mode 160000 index 00000000..3b1dbeba --- /dev/null +++ b/POSIX/Python/pybind11 @@ -0,0 +1 @@ +Subproject commit 3b1dbebabc801c9cf6f0953a4c20b904d444f879 diff --git a/POSIX/Python/test.py b/POSIX/Python/test.py new file mode 100644 index 00000000..7baeb2bf --- /dev/null +++ b/POSIX/Python/test.py @@ -0,0 +1,5 @@ +#!/ usr / bin / env python +#- * - coding : utf - 8 - * - +import mmkv + + if __name__ == '__main__' : mmkv.MMKV.initializeMMKV('.') m = mmkv.MMKV('test') diff --git a/Script/formatCode.py b/Script/formatCode.py index 37838763..95abb675 100644 --- a/Script/formatCode.py +++ b/Script/formatCode.py @@ -6,7 +6,7 @@ import os.path path = os.getcwd() for root, dirs, files in os.walk(path): - if root.endswith("/openssl") or root.endswith("/zlib") or (root.find("/build/generated/") != -1) or (root.find("cmake-build-debug/") != -1) or (root.find("cmake-build-release") != -1) or (root.find("CMakeFiles") != -1): + if (root.find("pybind11") != -1) or root.endswith("/openssl") or root.endswith("/zlib") or (root.find("/build/generated/") != -1) or (root.find("cmake-build-debug/") != -1) or (root.find("cmake-build-release") != -1) or (root.find("CMakeFiles") != -1): continue for name in files: if (name.endswith(".h") or name.endswith(".m") or name.endswith(".mm") or name.endswith(".hpp") or name.endswith(".cpp") or name.endswith(".java")):