C 如何在SQLite中编译用户定义函数

C 如何在SQLite中编译用户定义函数,c,macos,sqlite,create-function,C,Macos,Sqlite,Create Function,我有一个示例C函数,我想将其附加到数据库temp.sqlite(它来自O'Reilly的一本书,所以我知道它是有效的)。我读了书和sqlite.org中的部分,但他们认为我知道如何以及在哪里使用适当的设置编译这个东西。我在Mac(使用XCode)或Ubuntu上 我知道足够多的C语言来修改代码来实现我想要的功能,但我不知道该怎么做从我的数据库temp.sqlite调用它 谢谢你的帮助!我一直在忙这个 更新:再过几个小时,我从废弃的网页中收集了足够多的内容,创建了一个编译命令并生成了一个错误: r

我有一个示例C函数,我想将其附加到数据库
temp.sqlite
(它来自O'Reilly的一本书,所以我知道它是有效的)。我读了书和sqlite.org中的部分,但他们认为我知道如何以及在哪里使用适当的设置编译这个东西。我在Mac(使用XCode)或Ubuntu上

我知道足够多的C语言来修改代码来实现我想要的功能,但我不知道该怎么做从我的数据库
temp.sqlite
调用它

谢谢你的帮助!我一直在忙这个

更新:再过几个小时,我从废弃的网页中收集了足够多的内容,创建了一个编译命令并生成了一个错误:

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,这里是wtavg.c,它直接来自我书中提供的O'Reilly站点:

/* 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;
}
/*wtavg.c*/
#包括“sqlite3ext.h”
SQLITE_扩展_INIT1;
#包括
类型定义结构平均状态{
两倍总数据;/*值(数据*权重)之和*/
重量值总和的两倍*/
}wt_平均状态;
静态void wt_avg_步骤(sqlite3_上下文*ctx,int num_值,sqlite3_值**值)
{
双列_wt=1.0;
int型;
wt_avg_state*st=(wt_avg_state*)sqlite3_aggregate_context(ctx,
sizeof(wt_平均状态);
if(st==NULL){
sqlite3结果错误名称(ctx);
返回;
}
/*提取重量,如果我们有一个重量,它看起来像一个数字*/
如果(num_值==2){
type=sqlite3\u value\u numeric\u type(值[1]);
if((type==SQLITE_FLOAT)| |(type==SQLITE_INTEGER)){
row_wt=sqlite3_value_double(值[1]);
}
}
/*提取数据,如果给我们一些看起来像数字的东西*/
type=sqlite3_value_numeric_type(值[0]);
if((type==SQLITE_FLOAT)| |(type==SQLITE_INTEGER)){
st->total_data+=行wt*sqlite3_值双精度(值[0]);
st->总重量+=行重量;
}
}
静态void wt_avg_final(sqlite3_上下文*ctx)
{
双结果=0.0;
wt_avg_state*st=(wt_avg_state*)sqlite3_aggregate_context(ctx,
sizeof(wt_平均状态);
if(st==NULL){
sqlite3结果错误名称(ctx);
返回;
}
如果(st->总重量!=0.0){
结果=st->总数据/st->总数据;
}
sqlite3结果双精度(ctx,结果);
}
int wtavg_init(sqlite3*db,字符**错误,常量sqlite3\u api\u例程*api)
{
SQLITE_扩展_INIT2(api);
sqlite3_创建_函数(db,“wtavg”,1,SQLITE_UTF8,
空、空、wt_平均值步骤、wt_平均值最终);
sqlite3_创建_函数(db,“wtavg”,2,SQLITE_UTF8,
空、空、wt_平均值步骤、wt_平均值最终);
返回SQLITE_OK;
}

用户定义函数应编译为共享库文件:

gcc -shared -fPIC -o wtavg.so wtavg.c -lsqlite3
然后可以使用SQLite语句加载该共享库:

SELECT load_extension('/path/to/wt_avg.so', 'wtavg_init');
不幸的是,Apple提供的sqlite3版本不支持加载共享库。您可以改用MacPorts中的sqlite。链接sqlite的MacPorts程序也应该能够以这种方式加载用户定义的函数


但是,当在另一个程序中使用SQLite时,出于安全原因,可能会禁用扩展加载机制。例如,在Python中,您必须调用
con.enable\u load\u extension(True)
来启用它。

用户定义的函数应编译为共享库文件:

gcc -shared -fPIC -o wtavg.so wtavg.c -lsqlite3
然后可以使用SQLite语句加载该共享库:

SELECT load_extension('/path/to/wt_avg.so', 'wtavg_init');
不幸的是,Apple提供的sqlite3版本不支持加载共享库。您可以改用MacPorts中的sqlite。链接sqlite的MacPorts程序也应该能够以这种方式加载用户定义的函数


但是,当在另一个程序中使用SQLite时,出于安全原因,可能会禁用扩展加载机制。例如,在Python中,您必须调用
con.enable\u load\u extension(True)
来启用它。

gcc默认编译并链接一个完整的程序,这就是它抱怨缺少主入口点的原因。您可能会更幸运地编译一个共享库
gcc-shared-fPIC
尝试类似
gcc-shared-fPIC-o wtavg.so wtavg.c-Wall-W-O2-L/usr/local/lib-lsqlite3
。。。或者
选择load_extension('wtavg.so','wtavg_init')我猜,因为wtavg_init似乎是您的入口点。刚刚在Mac上尝试过,它似乎/usr/bin/sqlite3不支持动态扩展加载。我能够编译您的扩展并从MacPorts用sqlite3加载它。这和您最初的问题有些无关。。。。从另一个程序使用SQLite库的MacPorts版本最安全的方法可能是使用该程序的MacPorts版本。假设PythonMacPort而不是Apple.gcc中的Python默认编译并链接一个完整的程序,这就是它抱怨缺少主入口点的原因。您可能会更幸运地编译一个共享库
gcc-shared-fPIC
尝试类似
gcc-shared-fPIC-o wtavg.so wtavg.c-Wall-W-O2-L/usr/local/lib-lsqlite3
。。。或者
选择load_extension('wtavg.so','wtavg_init')我猜,因为wtavg_init似乎是您的入口点。刚刚在Mac上尝试过,它似乎/usr/bin/sqlite3不支持动态扩展加载。我能够编译您的扩展并从MacPorts用sqlite3加载它。这和您最初的问题有些无关。。。。从另一个程序使用SQLite库的MacPorts版本最安全的方法可能是使用该程序的MacPorts版本。用Python MacPort代替苹果的Python。非常感谢!今天早上在你的帮助下我学到了很多!非常感谢你!今天早上在你的帮助下我学到了很多!