Pregunta

I tiene una función de ejemplo de C que me gustaría conectar a una base de datos de temp.sqlite (que es a partir de un libro de O'Reilly, así que sé que funciona). He leído la sección en el libro y sqlite.org, pero asumen distancia, que yo sepa cómo y dónde para compilar esta cosa con la configuración adecuada. Estoy en cualquiera de Mac (con XCode) o Ubuntu.

Sé lo suficiente C para alterar el código para hacer lo que quiera, pero no tengo ni idea de qué hacer llamar desde mi temp.sqlite base de datos.

Gracias por su ayuda! He estado produciendo en esto!

Actualización: Un par de horas más en y he desechó cosas juntos lo suficiente de páginas abandonadas para crear un comando de compilación y generar un error:

richard$ gcc -o wtavg wtavg.c -Wall -W -O2 -L/usr/local/lib -lsqlite3
wtavg.c: In function ‘wtavg_init’:
wtavg.c:63: warning: unused parameter ‘error’
Undefined symbols:
  "_main", referenced from:
      start in crt1.10.6.o
ld: symbol(s) not found
collect2: ld returned 1 exit status

Fwiw, de aquí wtavg.c, que es directamente desde el sitio O'Reilly proporcionado en mi libro:

/* wtavg.c */

#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1;

#include <stdlib.h>




typedef struct wt_avg_state_s {
   double   total_data;  /* sum of (data * weight) values */
   double   total_wt;    /* sum of weight values */
} wt_avg_state;


static void wt_avg_step( sqlite3_context *ctx, int num_values, sqlite3_value **values )
{
    double         row_wt = 1.0;
    int            type;
    wt_avg_state   *st = (wt_avg_state*)sqlite3_aggregate_context( ctx,
                                               sizeof( wt_avg_state ) );
    if ( st == NULL ) {
        sqlite3_result_error_nomem( ctx );
        return;
    }

    /* Extract weight, if we have a weight and it looks like a number */
    if ( num_values == 2 ) {
        type = sqlite3_value_numeric_type( values[1] );
        if ( ( type == SQLITE_FLOAT )||( type == SQLITE_INTEGER ) ) {
            row_wt = sqlite3_value_double( values[1] );
        }
    }

    /* Extract data, if we were given something that looks like a number. */
    type = sqlite3_value_numeric_type( values[0] );
    if ( ( type == SQLITE_FLOAT )||( type == SQLITE_INTEGER ) ) {
        st->total_data += row_wt * sqlite3_value_double( values[0] );
        st->total_wt   += row_wt;
    }
}


static void wt_avg_final( sqlite3_context *ctx )
{
    double         result = 0.0;
    wt_avg_state   *st = (wt_avg_state*)sqlite3_aggregate_context( ctx,
                                               sizeof( wt_avg_state ) );
    if ( st == NULL ) {
        sqlite3_result_error_nomem( ctx );
        return;
    }

    if ( st->total_wt != 0.0 ) {
        result = st->total_data / st->total_wt;
    }
    sqlite3_result_double( ctx, result );
}


int wtavg_init( sqlite3 *db, char **error, const sqlite3_api_routines *api )
{
    SQLITE_EXTENSION_INIT2(api);

    sqlite3_create_function( db, "wtavg", 1, SQLITE_UTF8,
            NULL, NULL, wt_avg_step, wt_avg_final );
    sqlite3_create_function( db, "wtavg", 2, SQLITE_UTF8,
            NULL, NULL, wt_avg_step, wt_avg_final );

    return SQLITE_OK;
}
¿Fue útil?

Solución

La función definida por el usuario debe ser compilado como archivo de biblioteca compartida:

gcc -shared -fPIC -o wtavg.so wtavg.c -lsqlite3

Esa biblioteca compartida se puede cargar utilizando una sentencia SQLite:

SELECT load_extension('/path/to/wt_avg.so', 'wtavg_init');

Por desgracia, la versión de sqlite3 proporcionado por Apple no soporta bibliotecas compartidas de carga. Se puede utilizar SQLite desde MacPorts lugar. macports programas que unen contra SQLite también deben tener la capacidad de carga de las funciones definidas por el usuario de esta manera.

Cuando se utiliza SQLite dentro de otro programa sin embargo, el mecanismo de extensión de carga puede ser desactivado por motivos de seguridad. En Python, por ejemplo, usted tiene que con.enable_load_extension(True) llamada para que pueda.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top