我正在使用Xamarin.iOS上的Sqlite自定义功能。我从这里得到答案:Show markers on map within a given radius (Xamarin.Android)但是我遇到了
的问题尝试JIT编译方法'(包装器本机到托管) Mono.Data.Sqlite.SqliteFunction:ScalarCallback(intptr,int,intptr)' 使用--aot-only运行时。
在堆栈上搜索后,我发现这是一个解决方案:custom functions SQLite with Mono但解决方案提到我很难理解。
我不确定如何使用MonoPInvokeCallbackAttribute
注释方法并将其设置为静态,因为SqliteFunction类中的方法被覆盖,因此无法使其成为静态。
如果有人可以帮助我理解该解决方案或在该解决方案上提供缺失的步骤,那将是很好的。
答案 0 :(得分:2)
我使用受欢迎的$ctrl
(由Frank A. Krueger提供),然后使用sqlite-net
和SQLitePCLRaw.bundle_green
(均由Eric Sink提供)。
因此,您可以使用基于SQLitePCL.raw
的API轻松设置和访问SQLite UDF。
SQLitePCLRaw.ugly
的{{1}}用户定义函数(Xamarin.iOS
):SQLite
UDF
设置表,加载/更新数据,..... delegate void SQLiteCallback(sqlite3_context ctx, object user_data, sqlite3_value[] args);
[MonoPInvokeCallback(typeof(SQLiteCallback))]
static void UDFDistanceFunction(sqlite3_context ctx, object user_data, sqlite3_value[] args)
{
double radius = 6367;
var lat1 = raw.sqlite3_value_double(args[0]);
var lng1 = raw.sqlite3_value_double(args[1]);
var lat2 = raw.sqlite3_value_double(args[2]);
var lng2 = raw.sqlite3_value_double(args[3]);
var result = radius * 2 * Math.Asin(Math.Min(1, Math.Sqrt((Math.Pow(Math.Sin((lat2 * (Math.PI / 180) - lat1 * (Math.PI / 180)) / 2.0), 2.0) + Math.Cos(lat1 * (Math.PI / 180)) * Math.Cos(lat2 * (Math.PI / 180)) * Math.Pow(Math.Sin((lng2 * (Math.PI / 180) - lng1 * (Math.PI / 180)) / 2.0), 2.0)))));
raw.sqlite3_result_double(ctx, result);
}
sqlite-net-pcl
创建和查询带有SQLite UDF SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_sqlite3());
var dbName = Path.Combine(Path.GetTempPath(), "StackOverflow.db");
var db = new SQLiteConnection(dbName, SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create, true);
db.CreateTable<BarLocations>();
db.Insert(new BarLocations()
{
name = "FOOBAR", lat = 47.60357, lng = -122.3295
});