• Jueves 14 de Noviembre de 2024, 23:09

Autor Tema:  C++ y SQL  (Leído 3813 veces)

lydia_watanabe

  • Miembro activo
  • **
  • Mensajes: 27
    • Ver Perfil
C++ y SQL
« en: Sábado 14 de Marzo de 2009, 14:00 »
0
Hola a todos

Estoy trabajando en una aplicación en c++ (trabajando en Linux), la cual tiene que conectar a una base de datos (BD) usando SQLite3. La BD está creada, ahora mi problema es que no sé que librería debo incluir para poder trabajar con ella.

Según un ejemplo que he encontrado era tan sencillo como poner

Código: C++
  1. #include "sqlite3.h"
  2.  

o también

Código: C++
  1. #include <sqlite3.h>
  2.  

Pero al compilar me da el típico error de que no existe

Código: Text
  1. sqlite3.h: No existe el fichero ó directorio
  2.  

¿Alguien tiene idea de como puedo incluir la librería? Muchas gracias

EI: juntando mensajes.

Problema solucionado, hay que instalar libsqlite3-dev que me faltaba.

lydia_watanabe

  • Miembro activo
  • **
  • Mensajes: 27
    • Ver Perfil
Re: C++ y SQL
« Respuesta #1 en: Sábado 14 de Marzo de 2009, 18:39 »
0
Más problemas (cómo era de esperar).

Téngo un código sencillo y totalmente estúpido de prueba:

Código: C++
  1. #include <stdio.h>
  2. #include <sqlite3.h>
  3.  
  4. int main(int argc, char*argv[]){
  5.  
  6.    sqlite3* db;
  7.    sqlite3_open("bd/prueba.bd", &db);
  8.    if (sqlite3_errcode(db) != 0)
  9.       printf("%sn",sqlite3_errmsg(db));
  10.    sqlite3_close(db);
  11. }
  12.  

Nada del otro mundo, conecta con la BD, comprueba errores y cierra, pero me falla.

Código: Text
  1. bd.C:(.text+0xa0): undefined reference to `sqlite3_open'
  2. bd.C:(.text+0xab): undefined reference to `sqlite3_errcode'
  3. bd.C:(.text+0xbf): undefined reference to `sqlite3_errmsg'
  4. bd.C:(.text+0xd2): undefined reference to `sqlite3_close'
  5.  

No sé si tengo que incluir alguna otra librería en el código (que se supone que no) o si se debe a otra cosa (que será lo más probable).

Actualizado.- Despues de ponerme a investigar un poquillo más en profundida, descubrí que el problema estaba al compilar

Código: Text
  1. g++ -lsqlite3 bd.C
  2.  

Espero que mis dudas y mis propias respuestas les sirvan a otros también

lydia_watanabe

  • Miembro activo
  • **
  • Mensajes: 27
    • Ver Perfil
Re: C++ y SQL
« Respuesta #2 en: Domingo 15 de Marzo de 2009, 02:25 »
0
Dos nuevas preguntas, una es más de SQLite y la otra más de C++, pero ojalá que alguien me las sepa contestar.

Siguiendo un sencillo ejemplo de la página oficial de SQLite donde se muestra de forma muy básica como se conecta una BD, se hace una consultas y se cierra la conexión, he creado consulta simple en la que se busca en la BD un nombre de usuario y una clave introducidos al ejecutar el programa y se muestra el Identificador y el tipo de usuario.

Código: C++
  1. /**************************************************************************/
  2. int Callback(void *NotUsed, int argc, char **argv, char **azColName){
  3.  
  4.    cout << "Ident = " << argv[0] << "     TypeUser = " << argv[3] << endl;
  5.    return 0;
  6. }
  7.  
  8. /**************************************************************************/
  9. Users::Users(string name, string pass){
  10.    sqlite3* db;
  11.    char *zErrMsg = 0;
  12.  
  13.    sqlite3_open("bd/project.bd", &db);
  14.    if (sqlite3_errcode(db)!=0){
  15.       cout << sqlite3_errmsg(db) << endl << endl;
  16.       sqlite3_close(db);
  17.       exit(1);
  18.    }
  19.  
  20.    string select = "SELECT * FROM user WHERE username='" + name + "' and userpass='" + pass + "'";
  21.    int rc = sqlite3_exec(db, select.c_str(), Callback, 0, &zErrMsg);
  22.    if (rc != SQLITE_OK){
  23.       fprintf(stderr, "SQL error: %sn", zErrMsg);
  24.       sqlite3_free(zErrMsg);
  25.    }
  26.  
  27.    sqlite3_close(db);
  28. }
  29.  

Problema 1
Cuando lo ejecuto funciona perfectamente. Si existe el usuario, se muestra y si no existe no, el problema es si quiero hacer algo en especal cuando este usuario no existe, pues aparentemente no hay ningún tipo de variable o función que me lo indique, pero por lógica debería de haberla. ¿Existe alguna manera de saber si se han obtenido valores o no en la consulta?

Problema 2
Estoy trabajando con clases y por tanto me interesaría que la función Callback fuera un miembro de la clase para poder manejar ciertos datos, pero al compilar me da el siguiente error:

Código: Text
  1. error: el argumento de tipo ‘int (Users::)(void*, int, char**, char**)’ no coincide con ‘int (*)(void*, int, char**, char**)’
  2.  

¿Hay alguna manera de que la función pertenezca a la clase?

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: C++ y SQL
« Respuesta #3 en: Domingo 15 de Marzo de 2009, 08:03 »
0
Para el problema 1 consulta la documentacion, yo lo hice y no me parecio ver nada util.

Para el problema 2 tenes que hacer la funcion estatica, no tiene this y por eso justamente existe el parametro del callback que nombraste NotUsed, ahi le tenes que pasar el puntero del objeto, despues dentro del callback haces un cast y listo.

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

lydia_watanabe

  • Miembro activo
  • **
  • Mensajes: 27
    • Ver Perfil
Re: C++ y SQL
« Respuesta #4 en: Domingo 15 de Marzo de 2009, 15:07 »
0
Eternal Idol gracias por responder.

Con respecto al problema 1, la verdad es que consulté la documentación, pero no vi nada, sin embargo, podría ser que estuviera en alguna parte y que a mi se me hubiese pasado.

Con respecto al problema 2, entiendo lo que me dices, pero no tengo ni idea de como se hace. Nunca he usado el puntero this y estoy un poco perdida. Así pues ¿que modificaciones debería hacer si mi código de partida es este y como debería trabajar con sus parámetros?

Código: C++
  1. static int Users::Callback(void *NotUsed, int argc, char **argv, char **azColName){
  2.  
  3.    cout << "Ident = " << argv[0] << "     TypeUser = " << argv[3] << endl;
  4.    return 0;
  5. }
  6.  

Gracias

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: C++ y SQL
« Respuesta #5 en: Domingo 15 de Marzo de 2009, 15:41 »
0
Cita de: "lydia_watanabe"
Eternal Idol gracias por responder.

De nadas.

Cita de: "lydia_watanabe"
Con respecto al problema 1, la verdad es que consulté la documentación, pero no vi nada, sin embargo, podría ser que estuviera en alguna parte y que a mi se me hubiese pasado.

Yo tampoco, tal vez tengas que usar otra funcion ...

Cita de: "lydia_watanabe"
Con respecto al problema 2, entiendo lo que me dices, pero no tengo ni idea de como se hace. Nunca he usado el puntero this y estoy un poco perdida. Así pues ¿que modificaciones debería hacer si mi código de partida es este y como debería trabajar con sus parámetros?

En este caso no parece ser muy util ya que no accedes a ningun miembro de la clase pero supongamos que en Users hay un miembro llamado Edad:

Código: Text
  1.  
  2. static int Users::Callback(void *NotUsed, int argc, char **argv, char **azColName)
  3. {
  4.    Users *thisUser = (Users*)NotUsed;
  5.    cout << "Ident = " << argv[0] << "     TypeUser = " << argv[3] << " edad: " << thisUser->Edad << endl;
  6.    return 0;
  7. }
  8.  

Entonces el cuarto parametro de sqlite3_exec seria this en lugar de 0 asi NotUsed sera el puntero al objecto cuando sea llamada.

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

lydia_watanabe

  • Miembro activo
  • **
  • Mensajes: 27
    • Ver Perfil
Re: C++ y SQL
« Respuesta #6 en: Domingo 15 de Marzo de 2009, 16:21 »
0
La idea es precisamente la de darle valores a miembros de la clase con los valores obtenidos de las consultas, la cuestión es que cuando compilo, si declaro la función static me da este error:

Código: Text
  1. error: no se puede declarar que la función miembro ‘static int Users::Callback(void*, int, char**, char**)’ tenga enlazado estático
  2.  

y si no es static, pues me da el error que puse más arriba.

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: C++ y SQL
« Respuesta #7 en: Domingo 15 de Marzo de 2009, 17:54 »
0
Necesitaria ver el codigo (si queres reducilo a la minima expresion compilable) y el output exacto generado por el compilador, desde ya te digo que static solo debe ir dentro de la clase.

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

lydia_watanabe

  • Miembro activo
  • **
  • Mensajes: 27
    • Ver Perfil
Re: C++ y SQL
« Respuesta #8 en: Domingo 15 de Marzo de 2009, 18:04 »
0
Gracias, encontré el problema y lo solucioné, pero no me dio tiempo de decirlo por aquí. Y ahora se me plantea otra cuestión (que ojalá sea la última, porque si no creo que me volveré loca).

Siguiendo el ejemplo que me has puesto he hecho lo siguiente:

Código: C++
  1. int Users::Callback(void *NotUsed, int argc, char **argv, char **azColName){
  2.    Users *thisUser = (Users*)NotUsed;
  3.  
  4.    thisUser->Ident = atoi(argv[0]);    // Ident es un integer
  5.  
  6.    return 0;
  7. }
  8.  

Compila, pero al ejecutar da un Segmentation Fault.

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: C++ y SQL
« Respuesta #9 en: Domingo 15 de Marzo de 2009, 18:51 »
0
Depuralo y mira el NotUsed, puede que sea 0 sino cambiaste el parametro a sqlite3_exec como te dije antes y sino es que el objeto ya fue destruido ...

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

lydia_watanabe

  • Miembro activo
  • **
  • Mensajes: 27
    • Ver Perfil
Re: C++ y SQL
« Respuesta #10 en: Domingo 15 de Marzo de 2009, 19:11 »
0
Dios, a ver si me aclaro ¿cómo es que debería invocar a la función sqlite3_exec? (siento ser tan plasta, creo que empiezo a saturarme y eso no es bueno :brickwall: )

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: C++ y SQL
« Respuesta #11 en: Domingo 15 de Marzo de 2009, 19:25 »
0
int sqlite3_exec(
  sqlite3*,                                  /* An open database */
  const char *sql,                           /* SQL to be evaluated */
  int (*callback)(void*,int,char**,char**),  /* Callback function */
 void *,                                    /* 1st argument to callback */
  char **errmsg                              /* Error msg written here */
);

Entonces:
int rc = sqlite3_exec(db, select.c_str(), Callback, this, &zErrMsg);

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.

lydia_watanabe

  • Miembro activo
  • **
  • Mensajes: 27
    • Ver Perfil
Re: C++ y SQL
« Respuesta #12 en: Domingo 15 de Marzo de 2009, 21:24 »
0
Muchiiiiiiiiiisimas gracias, por fin puedo seguir tirando para adelante y la próxima vez que necesite usar de esto ya se como va el tema.

Eternal Idol

  • Moderador
  • ******
  • Mensajes: 4696
  • Nacionalidad: ar
    • Ver Perfil
Re: C++ y SQL
« Respuesta #13 en: Domingo 15 de Marzo de 2009, 21:44 »
0
De nadas  B)

Nacional y Popular En mi país la bandera de Eva es inmortal.


Queremos una Argentina socialmente justa, económicamente libre y  políticamente soberana.
¡Perón cumple, Evita dignifica!


La mano invisible del mercado me robo la billetera.