views:

328

answers:

3

I use a statically linked library for Sqlite in an iPhone Xcode project. I am now trying to include a .C extension to Sqlite in this project. However, I am having trouble making the Sqlite in the build SEE the extension.

The statically linked Sqlite library works fine. Also the .C extension works on my desktop, and builds fine as a statically linked library in Xcode. However, the custom functions it defines are missing when called.

For example, I load the extension as so with no errors.

SELECT load_extension('extension_name.so');

But when I try to call a function defined in the extension, I get this message

DB Error: 1 "no such function: custom_function"

Does anyone know much about linking a Sqlite extension into an Xcode project?

A: 

Would it be possible for you to build your custom functions directly into your main executable, and tell sqlite about them with sqlite3_create_function?

I don't know what details apply in this situation, but I do recall that the iPhone is funny about loading code at runtime.

Andrew
A: 

The function load_extension loads a shared library (.so). This is not allowed on the iPhone. You will have to recompile your static library to include the extension you wish to use.

jbworld
This sounds about right. I have tried adding my extension as a static library via New Target. However I it did not seem to be visible to the custom version of SQlite I included.Any suggestions or hints you can think of? Thanks heaps!
crunchyt
+2  A: 

As said by @jbworld you cannot load dynamic libraries on the iPhone, so this link should be made statically, at compilation time. While reading at the code of spatialite (that's an SQLite extension), I found that kind of invocation:

void spatialite_init (int verbose) {
/* used when SQLite initializes SpatiaLite via statically linked lib */
    sqlite3_auto_extension ((void (*)(void)) init_static_spatialite);
}

And the init_static_spatialite code:

static void init_static_spatialite (sqlite3 * db, char **pzErrMsg,
            const sqlite3_api_routines * pApi)
{
    SQLITE_EXTENSION_INIT2 (pApi);
/* setting the POSIX locale for numeric */
    setlocale (LC_NUMERIC, "POSIX");
    *pzErrMsg = NULL;
    sqlite3_create_function (db, "spatialite_version", 0, SQLITE_ANY, 0,
                             fnct_spatialite_version, 0, 0);
    sqlite3_create_function (db, "proj4_version", 0, SQLITE_ANY, 0,
                             fnct_proj4_version, 0, 0);
    sqlite3_create_function (db, "geos_version", 0, SQLITE_ANY, 0,
                             fnct_geos_version, 0, 0);
    sqlite3_create_function (db, "GeometryConstraints", 3, SQLITE_ANY, 0,
                             fnct_GeometryConstraints, 0, 0);
    sqlite3_create_function (db, "CheckSpatialMetaData", 0, SQLITE_ANY, 0,
                             fnct_CheckSpatialMetaData, 0, 0);
...

So it looks like if the sqlite_auto_extension enables you to statically link an extension. The documentation seems to confirm that:

“This API can be invoked at program startup in order to register one or more statically linked extensions that will be available to all new database connections.”

Then, at runtime, for spatialite, I just have to invoke the spatialite_init(0) to get the extension up and running.

Invoke such method before loading any sqlite DB.

Hope this helps.

yonel
Yonel - I'll have to look into this in a couple of days. I voted you up for persistence and helpfulness. Promise you a tick too when I can verify. Cheers!
crunchyt