Using SQLite with Unreal (on iOS)
This post documents the steps needed to use sqlite within a UE4 game on ios.
SQLite is awesome. It is a lightweight, self-contained database engine. It is often embedded in mobile apps because of its small footprint. For example, it is the common backing store for CoreData on ios. It enables you to utilize a relational database for your game and access it using sql.
How to embed Sqlite:
The common way to utilize third-party code in UE is using libraries. Luckily, there are a few builtin sqlite plugins for UE - I used https://github.com/KhArtNJava/SQLite3UE4. These work great for Windows, as there is are precompiled windows libraries available. (Although I had still had issues trying to share a project between Windows and mac - see below).
On Mac or iOS)
On the mac, locating and using a pre-compiled library is difficult.
As an alternative, we can use the preferred mechanism for embedding recommend by the sqlite project. e.g. we can use the Amalgamation….https://www.sqlite.org/amalgamation.html
The amalgamation is very cool - the entire sqlite engine is contained within a single .c file. Just add the .c and .h to any project, compile it, and call the sqlite c functions. Boom you are done. Why bother messing with a binary library when you can just include a single c file. Unfortunately, this approach only works on the mac because the ue build toolchain on windows chokes on the .c. I tried renaming the .c to .cpp, but then the pre-build include check fails on a bunch of included files. I am sure this is easy to resolve, but parts of the UE build chain are still a mystery to me. Eventually I did get a working project shared between Windows and Mac - see last note below.
So at a high level, the process on mac is simply:
Add the sqlite.c and sqlite.h files to your projects Source directory.
Call them from your c++ code or expose them to blueprints
One more thing for iOS
COPYING DATABASE (iOS Only)
The sqlite directory must be writable. On iOS, by default, the entire directory in which your game resources are deployed is not writable (the app bundle). One solution to this is to copy the “template sqlite file” deployed with your app to the apps “Documents” folder.
The documents folder is where Apple recommends you put files that your app reads and writes.
To get the location of this folder, you can use some objective-c code:
// your objc ios code here
UE_LOG(LogTemp, Warning, TEXT("In iPhone"));
NSArray * paths(NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES));
NSURL* url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
const char *docpath = [[url path] UTF8String];
UE_LOG(LogTemp, Warning, TEXT("path %s"),UTF8_TO_TCHAR(docpath));
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("path %s"),UTF8_TO_TCHAR(docpath)));
But you might say, that is obj-c code! How can UE compile it?
That is another bit of obscure UE magic. Obj-c embedded in cpp files compiles just fine!
The next issue is copying the packaged sqlite db into this writable documents directory.
//copy with ios
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *ns_db_path= [NSString stringWithUTF8String:TCHAR_TO_UTF8(*db_path)];
NSString *ns_TargetDB = [NSString stringWithUTF8String:TCHAR_TO_UTF8(*TargetDB)];
NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
NSError *error = nil;
[fileManager copyItemAtPath:ns_db_path toPath:ns_TargetDB error:&error];
Once you have copied over the sqlite db, you can use the standard SQLite library calls.
After jumping through all those hoops, using the c-interface for SQL is pretty easy if you know c and know sql.
There are tutorials all over:
Another great alternative is to leverage some of the Blueprint functions exposed by the SQLite3UE4 plugin.
I will a follow up post covering both of these approaches.....