Calling C from V
Example
#flag -lsqlite3
#include "sqlite3.h"
// See also the example from https://www.sqlite.org/quickstart.html
struct C.sqlite3 {
}
struct C.sqlite3_stmt {
}
type FnSqlite3Callback = fn (voidptr, int, &&char, &&char) int
fn C.sqlite3_open(&char, &&C.sqlite3) int
fn C.sqlite3_close(&C.sqlite3) int
fn C.sqlite3_column_int(stmt &C.sqlite3_stmt, n int) int
// ... you can also just define the type of parameter and leave out the C. prefix
fn C.sqlite3_prepare_v2(&C.sqlite3, &char, int, &&C.sqlite3_stmt, &&char) int
fn C.sqlite3_step(&C.sqlite3_stmt)
fn C.sqlite3_finalize(&C.sqlite3_stmt)
fn C.sqlite3_exec(db &C.sqlite3, sql &char, cb FnSqlite3Callback, cb_arg voidptr, emsg &&char) int
fn C.sqlite3_free(voidptr)
fn my_callback(arg voidptr, howmany int, cvalues &&char, cnames &&char) int {
unsafe {
for i in 0 .. howmany {
print('| ${cstring_to_vstring(cnames[i])}: ${cstring_to_vstring(cvalues[i]):20} ')
}
}
println('|')
return 0
}
fn main() {
db := &C.sqlite3(0) // this means `sqlite3* db = 0`
// passing a string literal to a C function call results in a C string, not a V string
C.sqlite3_open(c'users.db', &db)
// C.sqlite3_open(db_path.str, &db)
query := 'select count(*) from users'
stmt := &C.sqlite3_stmt(0)
// NB: you can also use the `.str` field of a V string,
// to get its C style zero terminated representation
C.sqlite3_prepare_v2(db, &char(query.str), -1, &stmt, 0)
C.sqlite3_step(stmt)
nr_users := C.sqlite3_column_int(stmt, 0)
C.sqlite3_finalize(stmt)
println('There are $nr_users users in the database.')
//
error_msg := &char(0)
query_all_users := 'select * from users'
rc := C.sqlite3_exec(db, &char(query_all_users.str), my_callback, voidptr(7), &error_msg)
if rc != C.SQLITE_OK {
eprintln(unsafe { cstring_to_vstring(error_msg) })
C.sqlite3_free(error_msg)
}
C.sqlite3_close(db)
}