티스토리 뷰
뭔문 및 참조 : https://github.com/jbandela/leveldb_cross_compiler
http://www.codeproject.com/Articles/569146/LevelDB-DLL-for-Windows-A-New-Approach-to-Exportin
LevelDB는 구글에서 개발한 key/value 저장소이다. 이것을 윈도우에서 빌드하는 것은 힘든 일이다.
이글을 쓰는 시점에서 http://code.google.com/p/leveldb/source/browse/WINDOWS?name=windows 는 가용한 글이 아님을 미리 밝혀둔다.
이 쓰레드에서 https://groups.google.com/forum/#!topic/leveldb/VuECZMnsob4 방안을 제시하지만, 역시 적절하지 않다.
Exporting a C++ class from a DLL can be hard if you want it be to be able to be used by different compilers. Alex Bleckhman as an excellent article here on Code Project titled HowTo: Export C++ classes from a DLL. However, doing that can still be a pain as you cannot use exceptions, C++ types such as std::string
. In addition, if you want to make a COM interface so you can have memory management and interface management, you still have a lot of code to write.
This article uses the free library at https://github.com/jbandela/cross_compiler_call to build a wrapper library for leveldb. The full code can be found here.
I packaged the needed files in the attached zip file. You can also get the file from here
Note, while there is a C wrapper for leveldb that I could have used, I decided to do it this way to try out the above library in developing something with real world use.
In this article, I will be talking about how the use the package. This will not be a tutorial on using cross_compiler_call to build something like this. If there is enough interest in the comments, I will write another article providing a walk-through of how this package was built.
배경
먼저, 나는 LevelDB 라이브러리를 만들어야 한다. 윈도우 상에서 빌드하기 위한 LevelDB 버전을 찾는 것은 어려운 일이었다.
첫번째 시도 : https://code.google.com/p/leveldbwin/
두번째 시도 : https://code.google.com/r/kkowalczyk-leveldb/
그러나, 이 글들은 leveldb의 오래된 버전에 대한 것이었다. 이리 저리 찾다가,....
세번째 시도:
GitHub에서 bitcoin을 발견했다. 나는 이것이 잘 관리되고 있다는 것을 직감했다.
소스내에서, 그들은 그들은 윈도우를 지원하는 leveldb를 관리하고 있었다. 그러나, 여기에도 역시 Visual C++ Project파일은 존재하지 않았다. 빌드하기 위해서 나는 MinGW g++을 사용했는데, 이것은 nuwen.net 에서 다운받아 설치했고, msys 를 ".a" 파일을 생성하는 shell로 사용하였다. 즉, leveldb 라이브러리를 빌드한 것이다.
그리고 나서, 나는 방금 생성한 ".a" 스타일의 라이브러리를 윈도우의 DLL로 만들기 위해서, leveldb_cc_dll.cpp 를 g++로 컴파일했다.
코드 사용하기
이 코드를 사용하는 예제를 위해, example.cpp를 보기 바란다.
당신은 variadic templates를 지원하는 C++ 11 버전이 필요하다.
당신이 만일 g++을 사용한다면, 당신은 명령행에 -std=c++11을 기입해야 하며, 이를 어길시에는 수많은 에러에 직면하게 될 것이다.(:-))
Visual C++에서 빌드하기 위해서, 당신은 'November CTP of Visual Studio 2012'가 필요할 것이며, 이것은 여기에서 다운받을 수 있다. 다음은 마이크로소프트의 릴리즈 노트 중에서 디테일 부분을 발췌한 것이다.
-
- "Visual C++ Compiler November 2012 CTP contains a preview
release of the Visual C++ compiler that adds the the following C++11 features to
the list of features already supported in Visual Studio 2012: uniform
initialization, initializer lists, variadic templates, function template default
arguments, delegating constructors, explicit conversion operators and raw
strings. A tour of these features is available on Channel 9 Core C++ episode 6:
http://aka.ms/vc-ctp-tour. More details on this release are available on the
Visual C++ Blog: http://aka.ms/vc-ctp-blog "
일단 이러한 것을 전부 얻었다면, 이제 당신은 example.cpp를 컴파일할 수 있다. 유의할 것은 level_db_cc.dll이 실행파일이 실행할 동일한 디렉터리에 있어야 한다는 것이다.
이제 example.cpp를 설명하도록 하겠다.
#include <iostream> #include "leveldb_cc/level_db_interfaces.h"
적색 표기된 줄에서 인터페이스 헤더를 포함하고 있다.
using namespace leveldb_cc;
leveldb interfaces는 leveldb_cc 네임스페이스 내에 있다
. 게다가, MSVC컴파일러는 버그를 가지고 있는데, 네임 룰업에 영향을 준다. 만일, 이를 포함하지 않으면, 당신은 Visual C++에서 컴파일러 에러에 직면하게 될 것이다.
int main(){
cross_compiler_interface::module m("leveldb_cc_dll");
이것은 명세된 DLL을 로드할 모듈을 생성한다. 여기서 주의할 점은 .dll확장자를 제거한 파일명을 기입해야 한다는 것이다. 윈도우 환경에서 .dll이고, 리눅스에서는 .so이다. 모듈은 스콥을 벗어나게 되면 라이브러리를 자동으로 언로드한다.:
auto creator = cross_compiler_interface::create_unknown(m,"CreateLevelDBStaticFunctions")
.QueryInterface<leveldb_cc::ILevelDBStaticFunctions>();
클래스 팩토리 인터페이스를 생성하기 위해서, DLL에 있는 함수 CreateLevelDBStaticFunctions 을 호출한다.
create_unknown
은 IUknown을 리턴한다
. 그래서, 우리는 ILevelDBStaticFunctions를 얻기 위해서 QueryInterface
를 호출한다..
// Open a scope so db goes out of scope so we can delete the database {
우리는 궁극적으로 데이터베이스를 지우기를 원하지만, 데이터베이스가 오픈되어 있을 때는 지울 수가 없다. 그래서, 우리는 하나의 스콥을 오픈했다. 이로인해, DB 오브젝트는 데이터베이스를 닫을때 사라질 것이다.
auto options = creator.CreateOptions(); options.set_create_if_missing(true); options.set_write_buffer_size(8*1024*1024); // Set cache of 1MB options.set_block_cache(creator.NewLRUCache(1024*1024)); // Set bloom filter with 10 bits per key options.set_filter_policy(creator.NewBloomFilterPolicy(10));
위 코드는 오픈되는 데이터베이스의 옵션을 생성한다. 우리는 데이터베이스가 존재하지 않는다면 생성하도록 하기 위해서 이를 세팅한다. 우리는 또한 LRUCache
와 BloomFilterPolicy를 셋업한다
.
// Open the db auto db = creator.OpenDB(options,"c:/tmp/testdb"); auto wo = creator.CreateWriteOptions(); wo.set_sync(false); // Add a few key/value pairs in a batch auto wb = creator.CreateWriteBatch(); wb.Put("Key1","Value1"); wb.Put("Key2","Value2"); wb.Put("Key3","Value3"); wb.Put("Key4","Value4"); wo.set_sync(true); db.WriteBatch(wo,wb); auto ro = creator.CreateReadOptions(); // Save a snapshot auto snapshot = db.GetSnapshot(); // Add more stuff to db db.PutValue(wo,"AfterSnapshot1","More Value1"); // Use the snapshot ro.set_snapshot(snapshot); auto iter = db.NewIterator(ro); std::cout << "Iterator with snapshot\n"; for(iter.SeekToFirst();iter.Valid();iter.Next()){ std::cout << iter.key().ToString() << "=" << iter.value().ToString() << "\n"; }; std::cout << "\n\n"; // Clear the snapshot ro.set_snapshot(nullptr); db.ReleaseSnapshot(snapshot); auto iter2 = db.NewIterator(ro); std::cout << "Iterator without snapshot\n"; for(iter2.SeekToFirst();iter2.Valid();iter2.Next()){ std::cout << iter2.key().ToString() << "=" << iter2.value().ToString() << "\n"; }; std::cout << "\n\n"; db.DeleteValue(wo,"Key1"); auto iter3 = db.NewIterator(ro); std::cout << "Iterator after delete Key1 snapshot\n"; for(iter3.SeekToFirst();iter3.Valid();iter3.Next()){ std::cout << iter3.key().ToString() << "=" << iter3.value().ToString() << "\n"; };
위 코드는 WriteBatch를 셋업하고 배치모드로 몇개의 키와 값을 쓴다. 그리고는 스냅샷을 저장한다. 그리고, 또다른 키와 값들을 반복적으로 스냅샷없이 추가한다. 코드는 값들을 지우고, 그 값이 지워졌다는 것을 보여준다.
}
// Delete the db
auto s = creator.DestroyDB("c:/tmp/testdb",creator.CreateOptions());
나중에 db가 스콥을 벗어나면('}') 우리는 그 데이터베이스를 제거한다.
'NoSQL' 카테고리의 다른 글
mongoose - An Embedded Web Server (0) | 2013.07.09 |
---|---|
leveldb - 윈도우 포팅 브랜치 버전 (0) | 2013.07.05 |
NoSQL Review (0) | 2013.03.06 |