Autore Topic: [C++] NDK e sqlite  (Letto 2654 volte)

Offline emaborsa

  • Utente normale
  • ***
  • Post: 274
  • Java Developer
  • Respect: +33
    • Google+
    • emaborsa
    • Mostra profilo
    • www.emaborsa.com
  • Dispositivo Android:
    Samsung Galaxy S2
  • Sistema operativo:
    Linux 10 - Win8.1 - Android 4.1.2
[C++] NDK e sqlite
« il: 12 Maggio 2011, 18:41:23 CEST »
0
Ammetto che sto facendo un progetto universitario, ma in rete non trovo soluzioni al mio problema. Abbiamo dovuto scrivere le classi in C++ per poi creare l'applicazione in Android con NDK. Non riesco a farlo nel build della libreria con NDK. Mi da sempre l'errore "undefined reference" e non so come fare. Molto probabilmente è solo una stringa in un file .mk, ma non reisco a scoprire quale.
Qualcuno mi sa dare una mano?

Offline bradipao

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 4043
  • keep it simple
  • Respect: +567
    • Github
    • Google+
    • bradipao
    • Mostra profilo
  • Dispositivo Android:
    Nexus 5
  • Play Store ID:
    Bradipao
  • Sistema operativo:
    W7
Re:[C++] NDK e sqlite
« Risposta #1 il: 12 Maggio 2011, 18:59:28 CEST »
0
Ciao, anche se vorrei, purtroppo non riesco ad aiutarti. Non ho mai nemmeno provato a guardare l'NDK. :-P

In generale l'argomento NDK è molto interessante, ma come avrai notato, la sezione ad esso dedicata è decisamente deserta, molto più di quanto vorremmo. Però la sezione esiste e almeno per quanto mi riguarda sarei felicissimo di vederla più frequentata da chi effettivamente ci lavora, magari anche proponendo semplici tutorial per attirare altri interessati con cui confrontare i problemi.  :-P

NON rispondo a domande nei messaggi privati
Bradipao @ Play Store

Offline Ricky`

  • Amministratore
  • Utente storico
  • *****
  • Post: 3489
  • Respect: +506
    • Github
    • Google+
    • rciovati
    • Mostra profilo
Re:[C++] NDK e sqlite
« Risposta #2 il: 12 Maggio 2011, 19:20:07 CEST »
0
Non sei stato molto dettagliato a dire il vero. Potresti postare un po' di codice' magari...

Offline emaborsa

  • Utente normale
  • ***
  • Post: 274
  • Java Developer
  • Respect: +33
    • Google+
    • emaborsa
    • Mostra profilo
    • www.emaborsa.com
  • Dispositivo Android:
    Samsung Galaxy S2
  • Sistema operativo:
    Linux 10 - Win8.1 - Android 4.1.2
Re:[C++] NDK e sqlite
« Risposta #3 il: 12 Maggio 2011, 20:36:17 CEST »
0
...cose centra il codice? Comunque se tu può "servire", te lo posto. Che cosa ti serve? Intanto ti posto la classe Database:

Database.h
Codice: [Seleziona]
/*
 * Database.h
 *
 *  Created on: Apr 11, 2011
 *      Author: manuel
 */

#ifndef DATABASE_H
#define DATABASE_H

#include <string>
#include "sqlite3.h"
#include "Item.h"
#include "TamagotchiIntelligence.h"
#include <vector>

class Random;
using namespace std;
using namespace Tamagotchi;
class Database {
public:
        Database();
        ~Database();
        bool open();
        bool saveGame(TamagotchiIntelligence*);
        TamagotchiIntelligence* loadGame(std::string);
        bool deleteSaveGame(std::string);
        vector<string> getSaveGames();
        Question* getRandomQuestion();
        Item* getRandomItem();
        bool doesSaveGameExist(std::string);
        bool close();

private:
        sqlite3 *databaseConnection;
        char* dataBaseName;
        int getRandomNumber(string);
};

#endif /* DATABASE_H_ */



Database.cpp
Codice: [Seleziona]
/*
 * Database.cpp
 *
 *  Created on: Apr 11, 2011
 *      Author: manuel
 */

#include "Database.h"
#include "State.h"
#include <cstring>
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <fstream>

/*
 * This is the Constructor of the class Database.
 * It initializes the variable of the database to NULL
 * and set the name of the fisical database file to
 * "sqlite3.database". At this moment the database is
 * NOT YET opened/connected/created!
 */
Database::Database() {
        databaseConnection = NULL;
        dataBaseName = "sqlite3.database"; // i'm not able to do a "right" conversion
        srand(time(NULL));
}

Database::~Database() {
        close();
}

/*
 * This method is used to create a connection to the database
 * using the function sqlite3_open(). If the database does NOT
 * exist it would be automaticallt created. As the SQLite definition,
 * if the connection is successfull, an OK-STATUS will be returned.
 *
 */
bool Database::open() {
    if (sqlite3_open(dataBaseName, &databaseConnection) == SQLITE_OK){
        return true;
    }
    return false;
}

/*
 * This method closes the connection to the database.
 */
bool Database::close() {
        if (sqlite3_close(databaseConnection) == SQLITE_OK)
                return true;
        return false;
}

/*
 * This method is used to save the game. It takes a TamagotchiIntelligence
 * obect, extract the data and creates the query string. The the string is
 * loaded to the database using the sqlite3_exec().
 */
bool Database::saveGame(TamagotchiIntelligence* aTamagotshi) {

        string name = (*aTamagotshi).getName();

        int age = aTamagotshi->getAge();
        string ageInString;
        {
                ostringstream oss;
                oss << age;
                ageInString = oss.str();
        }

        int stomach = aTamagotshi->getStomach();
        string stomachInString;
        {
                ostringstream oss;
                oss << stomach;
                stomachInString = oss.str();
        }

        int fun = aTamagotshi->getFun();
        string funInString;
        {
                ostringstream oss;
                oss << fun;
                funInString = oss.str();
        }

        string state = (aTamagotshi->getState())->getStateType();

        int dayHours = aTamagotshi->getDayHours();
        string dayHoursInString;
        {
                ostringstream oss;
                oss << dayHours;
                dayHoursInString = oss.str();
        }

        MoneyBox* aMoneyBox = aTamagotshi->getMoneyBox();

        int money = aMoneyBox->getBalance();
        string moneyInString;
        {
                ostringstream oss;
                oss << money;
                moneyInString = oss.str();
        }
        string vQuery;
        if (doesSaveGameExist(name)) {
            //TO DO ///////////////HERE WRITE THE UPDATE METHOD//TO DO
        }
        else  {
            vQuery = "INSERT INTO savegames (name, age, stomach, fun, dayhours, money, state) VALUES ('" + name + "',"+ ageInString + "," + stomachInString + ","+ funInString + "," + dayHoursInString + ","+ moneyInString + ",'" + state + "');";
         }
        char* ptrToQuery;
        ptrToQuery = &vQuery[0];
        char* db_err;
        sqlite3_exec(databaseConnection, ptrToQuery, NULL, 0, &db_err);
        string error = sqlite3_errmsg(databaseConnection);
        if (error != "not an error") {
                return false;
        }
        return true;
}


bool Database::deleteSaveGame(std::string name)
{
    string dQuery = "DELETE FROM savegames WHERE name = '" + name + "';";
    char* ptrToQuery;
    ptrToQuery = &dQuery[0];
    char* db_err;
    sqlite3_exec(databaseConnection, ptrToQuery, NULL, 0, &db_err);
    string error = sqlite3_errmsg(databaseConnection);
    if (error != "not an error") {
        cerr << error << "in deleting";
        return false;
    }
    return true;
}


vector<string> Database::getSaveGames()
{
        sqlite3_stmt *statement;
        vector<string> results;
        string aQuery = "SELECT name FROM savegames;";
        char* query = &aQuery[0];

        if(sqlite3_prepare_v2(databaseConnection, query, -1, &statement, 0) == SQLITE_OK)
        {
                int error = 0;
                while(true)
                {
                        error = sqlite3_step(statement);

                        if(error == SQLITE_ROW)
                        {
                            results.push_back((char*)sqlite3_column_text(statement, 0));
                        }
                        else
                        {
                                break;
                        }
                }

                sqlite3_finalize(statement);
        }

        string error = sqlite3_errmsg(databaseConnection);
        if(error != "not an error") cerr << query << " " << error << endl;

        return results;
}

/*
 * This method returns a random Question object from the database.
 */
Question* Database::getRandomQuestion() {
        string number;
        int aNumber = getRandomNumber("questions");
        ostringstream oss;
        oss << aNumber;
        number = oss.str();
        string
                        aQuery =
                                        "SELECT  question, rightanswer, wronganswer, award FROM questions WHERE number = "
                                                        + number + ";";
        sqlite3_stmt *pStmt;
        char* ptAQuery = &aQuery[0];
        if (sqlite3_prepare_v2(databaseConnection, ptAQuery, -1, &pStmt, 0)
                        != SQLITE_OK) {
                cerr << "db error (preparev2 in getRandomQuestion) : "
                                << sqlite3_errmsg(databaseConnection) << endl;
        }
        if (sqlite3_step(pStmt) != SQLITE_ROW) {
                cerr << "db error (step in getRandomQuestion): " << sqlite3_errmsg(
                                databaseConnection) << endl;
        }

        const unsigned char* ptQuestion = sqlite3_column_text(pStmt, 0);
        char* ptrQuestionChar = (char*) ptQuestion;
        string questionString = ptrQuestionChar;

        const unsigned char* ptRightAnswer = sqlite3_column_text(pStmt, 1);
        char* ptrRightAnswerChar = (char*) ptRightAnswer;
        string rightAnswerString = ptrRightAnswerChar;

        const unsigned char* ptWrongAnswer = sqlite3_column_text(pStmt, 2);
        char* ptWrongAnswerChar = (char*) ptWrongAnswer;
        string wrongAnswerString = ptWrongAnswerChar;

        int award = sqlite3_column_int(pStmt, 3);

        sqlite3_finalize(pStmt);

        return new Question(questionString, rightAnswerString, wrongAnswerString,
                        award);

}

bool Database::doesSaveGameExist(string saveGame)
{
    string aQuery = "SELECT name FROM savegames WHERE name = '" + saveGame + "';";
    sqlite3_stmt *pStmt;

    char* ptAQuery = &aQuery[0];
    if (sqlite3_prepare_v2(databaseConnection, ptAQuery, -1, &pStmt, 0)!= SQLITE_OK) {
        cerr << "db error (preparev2 in doesSaveGameExist): " << sqlite3_errmsg(
                        databaseConnection) << endl;
    }
    int error = sqlite3_step(pStmt) != SQLITE_ROW;

    sqlite3_finalize(pStmt);
    if (error) {
            return false;
    }
    return true;
}

/*
 * This method returns a random Item object from the database.
 */
Item* Database::getRandomItem() {

        //getting a random number from the table items
        int aNumber = getRandomNumber("items");
        string number;

        //converting the random number to a string
        {
                ostringstream oss;
                oss << aNumber;
                number = oss.str();
        }

        //getting the name price and happiness value from
        //the table itemns, accordingly to the random number
        //and converting the price and hapiness to int
        string aQuery =
                        "SELECT name, price, happiness, image FROM items WHERE number = "
                                        + number + ";";
        sqlite3_stmt *pStmt;

        char* ptAQuery = &aQuery[0];
        if (sqlite3_prepare_v2(databaseConnection, ptAQuery, -1, &pStmt, 0)
                        != SQLITE_OK) {
                cerr << "db error (preparev2 in getRandomItem): " << sqlite3_errmsg(
                                databaseConnection) << endl;
        }
        if (sqlite3_step(pStmt) != SQLITE_ROW) {
                cerr << "db error (step in getRandomItem): " << sqlite3_errmsg(
                                databaseConnection) << endl;
        }

        const unsigned char* ptName = sqlite3_column_text(pStmt, 0);
        char* ptNameChar = (char*) ptName;
        string nameString = ptNameChar;

        int price = sqlite3_column_int(pStmt, 1);

        int happiness = sqlite3_column_int(pStmt, 2);

        int imageSize = sqlite3_column_bytes(pStmt, 3);

        unsigned char* ptImage = (unsigned char*) malloc(imageSize);
        if (ptImage != NULL)

        memcpy(ptImage, sqlite3_column_blob(pStmt, 3), imageSize);
        sqlite3_finalize(pStmt);
        return new Item(nameString, price, happiness, ptImage, imageSize);


}

/*
 * This method load the data of the previous saved game.
 */
TamagotchiIntelligence* Database::loadGame(std::string name) {

        string aQuery =
                        "SELECT name, age, stomach, fun, money, state, dayhours FROM savegames WHERE name = '"+name+"';";
        sqlite3_stmt *pStmt;

        char* ptAQuery = &aQuery[0];
        if (sqlite3_prepare_v2(databaseConnection, ptAQuery, -1, &pStmt, 0)
                        != SQLITE_OK) {
                cerr << "db error (preparev2 in loadGame): " << sqlite3_errmsg(
                                databaseConnection) << endl;
        }
        if (sqlite3_step(pStmt) != SQLITE_ROW) {
                cerr << "db error (step in loadGame): " << sqlite3_errmsg(
                                databaseConnection) << endl;
        }

        const unsigned char* ptName = sqlite3_column_text(pStmt, 0);
        char* ptNameChar = (char*) ptName;
        string nameString = ptNameChar;

        int age = sqlite3_column_int(pStmt, 1);

        int stomach = sqlite3_column_int(pStmt, 2);

        int fun = sqlite3_column_int(pStmt, 3);

        int money = sqlite3_column_int(pStmt, 4);

        const unsigned char* ptState = sqlite3_column_text(pStmt, 5);
        char* ptStateChar = (char*) ptState;
        string stateString = ptStateChar;

        int dayHours = sqlite3_column_int(pStmt, 6);

        MoneyBox* aMoneyBox = new MoneyBox(money);

        State* aState = State::newState(stateString);

        bool adult;
        if (age > 18)
                adult = true;
        bool night;
        if (dayHours < 10 || dayHours > 20)
                night = true;

        sqlite3_finalize(pStmt);

        return new TamagotchiIntelligence(nameString, age, adult, stomach, fun,
                        dayHours, night, aState, aMoneyBox);;
}
/**
 *
 * [url=http://www.dreamincode.net/forums/topic/122300-sqlite-in-c/]SQLite In C++ - C++ Tutorials | Dream.In.Code[/url]
 *
 * esempio per blob:
 * found on [url=http://www.sqlite.org/cvstrac/wiki?p=BlobExample]SQLite CVSTrac[/url]
 *
 */

/*
 * This method returns a random number accordingly to
 * the entries of the passed table name in the database
 */
int Database::getRandomNumber(string tableName) {


        string aQuery = "SELECT count(*) FROM " + tableName + ";";
        sqlite3_stmt *pStmt;
        char* ptAQuery = &aQuery[0];
        if (sqlite3_prepare_v2(databaseConnection, ptAQuery, -1, &pStmt, 0)
                        != SQLITE_OK) {
                cerr << "db error (preparev2 in getRandomNumber): " << sqlite3_errmsg(
                                databaseConnection) << endl;
        }
        if (sqlite3_step(pStmt) != SQLITE_ROW) {
                cerr << "db error (step in getRandomNumber): " << sqlite3_errmsg(
                                databaseConnection) << endl;
        }

        int number = sqlite3_column_int(pStmt, 0);
        int randomNumber = rand() % number + 1;
        sqlite3_finalize(pStmt);
        number = 0;
        return randomNumber;
}



Comunque sia: Devo fare il build (creare libreria nativa) di classi C++ con NDK, ma dato che le classi fanno riferimento alla libreria libsqlite3.a (di linux), mi da errore....molto probabilmente perchè non riesco includerla nei make file.
« Ultima modifica: 12 Maggio 2011, 20:50:40 CEST da emaborsa »

Offline Ricky`

  • Amministratore
  • Utente storico
  • *****
  • Post: 3489
  • Respect: +506
    • Github
    • Google+
    • rciovati
    • Mostra profilo
Re:[C++] NDK e sqlite
« Risposta #4 il: 12 Maggio 2011, 21:33:05 CEST »
0
A me non sembra che ci siamo riferimenti all'ndk in questo codice.
Ma ti serve farlo chiamare poi da java tramite jni o ti serve compilarlo direttamente in c++ e farlo girare così com'è?

Offline emaborsa

  • Utente normale
  • ***
  • Post: 274
  • Java Developer
  • Respect: +33
    • Google+
    • emaborsa
    • Mostra profilo
    • www.emaborsa.com
  • Dispositivo Android:
    Samsung Galaxy S2
  • Sistema operativo:
    Linux 10 - Win8.1 - Android 4.1.2
Re:[C++] NDK e sqlite
« Risposta #5 il: 12 Maggio 2011, 22:01:21 CEST »
0
Scusa, ma penso che tu non abbia capito quello che devo fare. Io devo creare la libreria nativa. Ho il codice C++ e devo creare la mia so, per poi utilizzare le chiamate native.

Comunque se vuoi il nativo.cpp:

Codice: [Seleziona]
#include <stdio.h>
#include <jni.h>
#include "TamagotchiIntelligence.h"

using namespace Tamagotchi;
       
        TamagotchiIntelligence *current;

        extern "C"{
                JNIEXPORT void JNICALL Java_com_tamagotchi_NamingWindow_createTamagotchi(JNIEnv *env, jobject obj, jstring name);
                JNIEXPORT jstring JNICALL Java_com_tamagotchi_Panel_getName(JNIEnv *env, jobject obj);
                JNIEXPORT jint JNICALL Java_com_tamagotchi_NamingWindow_getFun(JNIEnv *env, jobject obj);
                JNIEXPORT jint JNICALL Java_com_tamagotchi_NamingWindow_hatch(JNIEnv *env, jobject obj);
                JNIEXPORT void JNICALL Java_com_tamagotchi_Recall_overTime(JNIEnv *env, jobject obj);
                JNIEXPORT jint JNICALL Java_com_tamagotchi_Recall_getDayHours(JNIEnv *env, jobject obj);
        };
       
        JNIEXPORT void JNICALL Java_com_tamagotchi_NamingWindow_createTamagotchi(JNIEnv *env, jobject obj, jstring name){
                const char *str = env->GetStringUTFChars(name, 0);
                current = new TamagotchiIntelligence(str);
        }
       
        JNIEXPORT jstring JNICALL Java_com_tamagotchi_Panel_getName(JNIEnv *env, jobject obj){
                string n = (*current).getName();
                char s[20];
                strcpy(s, n.c_str());
                jstring name = env->NewStringUTF(s);
                return name;
        }
       
        JNIEXPORT jint JNICALL Java_com_tamagotchi_NamingWindow_getFun(JNIEnv *env, jobject obj){
                jint funny = (*current).getFun();
                return funny;
        }
       
        JNIEXPORT jint JNICALL Java_com_tamagotchi_NamingWindow_hatch(JNIEnv *env, jobject obj){
                (*current).hatch();
                (*current).wakeUp();
                (*current).fulfill();
                (*current).starve();
                (*current).afflict();
                (*current).die();
                State *s = (*current).getState();
                jint prova = (*s).getProva();
                return prova;
        }
       
        JNIEXPORT void JNICALL Java_com_tamagotchi_Recall_overTime(JNIEnv *env, jobject obj){
                (*current).overTime();
        }
       
        JNIEXPORT jint JNICALL Java_com_tamagotchi_Recall_getDayHours(JNIEnv *env, jobject obj){
                jint hour = (*current).getDayHours();
                return hour;
        }
       


Che comunque è solo un test, e se nel NDK-BUILD non includo la classe Database e il sqlite3.h, funziona.

Offline 7h38ugg3r

  • Moderatore globale
  • Utente storico
  • *****
  • Post: 1200
  • Respect: +133
    • riccardofischetti
    • th38ugg3r
    • @7h38ugg3r
    • Mostra profilo
  • Dispositivo Android:
    Galaxy-S GT I-9000/ ASUS Eee Pad Transformer
  • Play Store ID:
    Riccardo Fischetti
  • Sistema operativo:
    OS X Lion / Linux Mint 11 (Katya)
Re:[C++] NDK e sqlite
« Risposta #6 il: 13 Maggio 2011, 12:28:28 CEST »
0
Ho avuto a che fare con ndk ma, per motivi di tempo, non ho mai potuto mettere un tutorial.

leggiti questi, che ti apriranno un mondo (forse).

http://mobile.tutsplus.com/tutorials/android/ndk-tutorial/
http://mobilepearls.com/labs/ndk-builder-in-eclipse/
7h38ugg3r<=>thebugger
Non conosci Java? Allora sei nel posto sbagliato!

http://www.androidpatterns.com/

Offline emaborsa

  • Utente normale
  • ***
  • Post: 274
  • Java Developer
  • Respect: +33
    • Google+
    • emaborsa
    • Mostra profilo
    • www.emaborsa.com
  • Dispositivo Android:
    Samsung Galaxy S2
  • Sistema operativo:
    Linux 10 - Win8.1 - Android 4.1.2
Re:[C++] NDK e sqlite
« Risposta #7 il: 14 Maggio 2011, 14:18:19 CEST »
0
Ho avuto a che fare con ndk ma, per motivi di tempo, non ho mai potuto mettere un tutorial.

leggiti questi, che ti apriranno un mondo (forse).

http://mobile.tutsplus.com/tutorials/android/ndk-tutorial/
http://mobilepearls.com/labs/ndk-builder-in-eclipse/

Grazie per l'interesse, ma io di android sono gia pratico, sia in Eclipse che non, e anche con le chiamate native. Il mio problema era il build della libreria, quando facevo ndk-build ...e tramite Android.mk e Application.mk dovrebbe caricarmi tutti i cpp e "sorgenti" dichiarati, per poi crearmi la .so...ma mi dava errori. Ho scoperto che non avevo i sorgenti corretti per il sqlite3. Scaricati quelli aggiornati me la compilava, anche se ho dovuto modificare una funzione nel .c