У меня проблемы с использованием объединения sqlite3 C / C ++ в контексте Unreal Engine 4 ...
Я могу открыть соединение с базой данных и записать в нее данные, проверяя это с помощью DB Browser, но выполнение операторов SELECT
с использованием sqlite3_prepare_v2
и sqlite3_step
приводит к неожиданному поведению. Я проверяю возвращаемые значения и не вижу никаких кодов ошибок, но я вижу SQLITE_DONE
, когда я ожидал бы увидеть SQLITE_ROW
, возвращенный sqlite3_step
. Если я выхожу из системы с результатом sqlite3_expanded_sql
, я получаю ожидаемый оператор со всеми правильно вставленными параметрами, и если я копирую и вставляю его в браузер БД, я получаю ожидаемые результаты.
Вытягиваемые данные указаны c при каждом запуске программы, поэтому я знаю, что не вижу старых или ненужных данных в браузере БД, и я знаю, что мои функции «записи» также работают должным образом.
Что особенно странно заключается в том, что после того, как закомментировал все ссылки на SQLPreparedStatementString
(который я использовал в попытке отладить проблему), код работает по-другому: теперь я возвращаю одну строку (вместо ожидаемых 4).
Это почти заставляет меня подозревать, что происходит проблема с памятью, возможно, sqlite3 и Unreal записывают в одни и те же разделы памяти, не сообщая об этом друг другу? Я склонен полагаться на управление памятью UE4 и не имею большого опыта работы с C / C ++ за пределами UE4, поэтому мои знания о таких вещах, как malloc
, в значительной степени ограничены общим ощущением, что «вот драконы» и т. Д. 1033 *. Я также понимаю, что sqlite3_prepare_v2
и sqlite3_step
- это функции, которые, как правило, выделяют много памяти, но если это вызывает проблему, я удивлен, что это происходит так редко, поскольку я успешно вызываю их несколько тысячу раз (для добавления данных) при каждом запуске игры.
Я понимаю, что можно установить параметры времени компиляции для sqlite, которые предварительно выделяют ему блок памяти, чтобы он не использовал mallo c вообще во время выполнения, но я еще не совсем понял, как это сделать в контексте включения объединения в UE4.
Соответствующий код ниже:
TArray<FName> UOzyBrainLogger::GetLoggedCivsForTurn(const int32 TurnNumber)
{
TArray<FName> rVal;
sqlite3_stmt *SQLStatement;
FString SQLCommand = "SELECT DISTINCT CivName FROM Decision WHERE (GameID = ? AND TurnNumber = ?) ;";
int rc;
rc = sqlite3_prepare_v2(DB, TCHAR_TO_UTF8(*SQLCommand), -1, &SQLStatement, NULL);
if (rc == SQLITE_OK)
{
//FString SQLPreparedStatementString;
UE_LOG(OzyBrainLogger, Log, TEXT("Getting Civs logged for turn %d in game %s"), TurnNumber, *GameID);
if(sqlite3_bind_text( SQLStatement, 1, TCHAR_TO_UTF8(*GameID), -1, SQLITE_STATIC) == SQLITE_OK &&
sqlite3_bind_int( SQLStatement, 2, TurnNumber) == SQLITE_OK)
{
//SQLPreparedStatementString = UTF8_TO_TCHAR(sqlite3_expanded_sql(SQLStatement));
//UE_LOG(OzyBrainLogger, Log, TEXT("Successfully created statement: %s"), *SQLPreparedStatementString);
rc = sqlite3_step(SQLStatement);
if (rc == SQLITE_DONE)
{
UE_LOG(OzyBrainLogger, Log, TEXT("No results found?"));
}
else if (rc != SQLITE_ROW)
{
UE_LOG(OzyBrainLogger, Log, TEXT("Return code was: %d"), rc);
}
while (rc == SQLITE_ROW)
{
FName CivName = FName(*FString(UTF8_TO_TCHAR((const char*) sqlite3_column_text(SQLStatement, 0))));
//UE_LOG(OzyBrainLogger, Log, TEXT("Returning %s for turn %d via statement: %s"), *CivName.ToString(), TurnNumber, *SQLPreparedStatementString);
UE_LOG(OzyBrainLogger, Log, TEXT("Returning %s for turn %d"), *CivName.ToString(), TurnNumber);
rVal.Add(CivName);
rc = sqlite3_step(SQLStatement);
}
}
else
{
UE_LOG(OzyBrainLogger, Warning, TEXT("%s"), UTF8_TO_TCHAR(sqlite3_errmsg(DB)));
}
}
else
{
UE_LOG(OzyBrainLogger, Warning, TEXT("%s"), UTF8_TO_TCHAR(sqlite3_errmsg(DB)));
}
sqlite3_finalize(SQLStatement);
return rVal;
}
Я мог бы упускать что-то действительно очевидное, но я не уверен, как исследовать это дальше, чтобы добиться прогресса, поэтому любые советы о путях исследования были бы очень полезны.
Я чувствую себя немного потерянным!