如何在 Objective-c 中使用 sqlite3_load_extension [错误:dlopen(...) image not found]

Posted

技术标签:

【中文标题】如何在 Objective-c 中使用 sqlite3_load_extension [错误:dlopen(...) image not found]【英文标题】:HOW TO sqlite3_load_extension from within Objective-c [error: dlopen(...) image not found] 【发布时间】:2010-02-21 03:11:48 【问题描述】:

我正在尝试加载 sqlite3 的扩展,以便在 iPhone 应用程序 Objective-c 代码中使用。我成功地将新函数的c文件编译成一个名为libsqlitefunctions.dylib的dylib。这是我有点失落的地方。我调用 sqlite3_load_extension 如下:

char *error = sqlite3_malloc(MAX_SQLITE_ERROR_MESSAGE_SIZE); const char *library = [@"libsqlitefunctions.dylib" UTF8String];

if (sqlite3_load_extension(database, library, 0, &error) != SQLITE_OK) message = [NSString stringWithFormat:@"%s", error];

sqlite3_free(错误);

无论我做什么,我都会收到错误:dlopen(libsqlitefunctions.dylib, 10): image not found

我试过了:

    指示 dylib 的完全限定路径 表示相对路径 没有指明路径(如上图) 将 dylib 添加为框架 将 .c 文件添加到我的项目中并将其编译为 .o 文件,然后尝试加载它

请注意,这不是入口点问题,因为我将 0 作为参数传递。这将通过调用 dylib 中定义的 init 函数来强制加载 dylib。我什至没有达到这一点。

与你们其他人相比,我几乎是一个新手,我觉得我可能对库的加载方式缺乏了解。

我真的很感激任何想法,因为使用这个库中的函数的能力对于我的应用程序的功能很重要。提前谢谢大家。

【问题讨论】:

【参考方案1】:

好的,我听取了您的建议,只是将我的新功能添加到我项目中的 sqlite3.c 文件中。它静态编译和链接并且工作正常。谢谢你的主意。我仍然想知道是什么阻止了我加载扩展程序,但很高兴在解决问题方面学到了其他东西——而且我赶上了最后期限。再次感谢。

【讨论】:

【参考方案2】:

经过几天的搜索,我终于找到了解决方案!

1) 一旦你的 sqlite_extension.h 和 sqlite_extension.c 文件移动到你的 sqlite_extension 文件夹中

2) cd 到那个 sqlite_extension 文件夹

3) 使用以下代码编译您的代码:

gcc -g -fPIC -std=gnu99 -current_version 1.0 -compatibility_version 1.0 -dynamiclib -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk -arch armv7 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk sqlite_extension.c -o sqlite_extension.dylib

您可能需要更改 ../iPhoneOSN.M.sdk 之类的 SDK 路径,其中 N.M 表示 ios 的最后可用版本,请查看文件夹“/Applications/Xcode.app/Contents/Developer/ Platforms/iPhoneOS.platform/Developer/SDKs/" 来查找现有路径

4) 您可以使用以下命令检查生成的文件:

file /path/to/your/sqlite_extension.dylib

应该返回类似:

/./././sqlite_extension.dylib (for architecture armv7): Mach-O dynamically linked shared library arm
/./././sqlite_extension.dylib (for architecture arm64): Mach-O 64-bit dynamically linked shared library

或者使用更详细的:

otool -l sqlite_extension.dylib

5) 现在您的库需要使用与嵌入应用程序相同的身份进行代码签名,您可以使用以下方法:

codesign -fs "your_apple_identity" sqlite_extension.dylib

your_apple_identity 的格式可以是“your_name: your_apple_login_email@address.xxx”

确保最好的方法是从使用 Xcode 在您的设备上编译和运行的嵌入式应用程序可执行文件中复制一个,或者使用以下命令复制计算机上的存档:

codesign --display --verbose=4 ~/Library/Developer/Xcode/Archives/2016-09-25/YourApp\ 25-09-2016\ 12.00.xcarchive/Products/Applications/YourApp.app/YourApp

用于代替“your_apple_identity”的字符串是在第一次出现 Authority= 之后找到的字符串

6) 库代码签名后,您可以使用相同的命令检查是否获得了与您的应用相似的签名信息:

codesign --display --verbose=4 sqlite_extension.dylib

7) 您的库现在已准备好嵌入到您的应用程序中,您只需确保 Xcode 刷新您的库文件(如果您曾尝试使用以前的同名文件)。为此,您可以删除以前的文件,在您的设备上编译和运行,放回新文件,确保它在“复制捆绑资源”中,而不是在应用程序的“构建阶段”选项卡的“链接二进制文件”中

当您的应用请求 SQLite 使用它时,您的扩展程序应该会正确加载


iOS 9.3.5 Xcode 8.0 SQLite 3.9.2

【讨论】:

【参考方案3】:

我不能 100% 确定这是明确禁止的,但 iPhone 不支持另一种类型的动态加载 - 框架。您可能需要静态编译和链接库,而不是动态。

【讨论】:

感谢您的回复。我实际上最初尝试静态链接。但是,我无法在 .o 文件上调用 sqlite3_load_extension 函数。我现在正在尝试重新设计 .c 代码,以便扩展库中的函数是相同 sqlite3.c 代码的一部分。有没有其他人在 iPhone 上的 objective-c 中调用 sqlite3_load_extension? 我很确定这在 iPhone 上是不允许的,因为动态加载代码要求文件既可读又可执行,并且不允许你执行权限在 iPhone 上。这与-[NSBundle load] 不起作用的原因相同。【参考方案4】:

我知道主题是旧的。但是谷歌搜索把我带到了这里。对于遇到此问题并最终出现在这里的任何人: 你必须先打电话 sqlite3_enable_load_extension(db, 1);

【讨论】:

【参考方案5】:

我知道我回复晚了,但我遇到了同样的问题并找到了如何加载扩展。

一旦你有源文件 X.c,编译一个共享库(在 Linux 机器上)使用

gcc -g -fPIC -shared X.c -o X.so

其中 X.c 是正在使用的扩展

然后启用在 C 接口中使用 SQLite 加载扩展

sqlite3_enable_load_extension(db,1);

然后使用

加载扩展
sqlite3_load_extension(db,"/path/of/extension/X.so","sqlite3_X_init",0);

就是这样,现在将加载扩展。

【讨论】:

以上是关于如何在 Objective-c 中使用 sqlite3_load_extension [错误:dlopen(...) image not found]的主要内容,如果未能解决你的问题,请参考以下文章

安卓应用版本升级时sqlit数据库升级

Sqlit--学习教程(命令)

Django学习手册 - sqlit数据库操作

busybox filesystem httpd php-5.5.31 sqlit3 webserver

如何在c++中,调用objective-c

Objective-C 观察者 - 如何在 Swift 中使用