我想做的是简单地从我的Java android活动中调用一个在我的C++代码库中实现的本地函数。签名可以是任何东西,但我们把它定义为 void fooBar()
.
我的工作空间是由gradle项目组成的树形结构,除了app是 "com.android.application "之外,其他都是 "com.android.library "项目。所有的项目都包含了某种形式的C++代码,还有一些包含了Java类。活动类在根项目("Core")中。函数的本地实现在同一个项目的.cpp文件中。
这是logcat的错误输出。
E/com.organization.app: No implementation found for void com.organization.app.Activity.a() (tried Java_com_organization_app_Activity_a and Java_com_organization_app_Activity_a__)
E/AndroidRuntime: FATAL EXCEPTION: Thread-9
Process: com.organization.app, PID: 3607
java.lang.UnsatisfiedLinkError: No implementation found for void com.organization.app.Activity.a() (tried Java_com_organization_app_Activity_a and Java_com_organization_app_Activity_a__)
at com.organization.app.Activity.a(Native Method)
at com.organization.app.Activity.onStart(Unknown Source:0)
当我在为Debug构建时,我可以调用这个。fooBar()
函数没有问题,但在Release中,它试图使用不同的名称加载函数。也就是: a()
. 本地端的函数签名没有问题,因为如果我简单地将函数名称改为 Java_com_organization_app_Activity_a
我还试着添加了更多的函数,这些函数的新名字变成了----------。b()
和 c()
,分别是。
似乎我在哪里调用函数并不重要,所以事实上它说的是 onStart
这里是无趣的。
我试着搜索有类似问题的人,但都是CC++中函数签名的问题。
我找到了解决方案。
我在Debug和Release之间做了一些交叉引用,发现要么关闭了 minifyEnabled
或删除proguard文件声明,使得异常消失了。之后,我查看了我使用的proguard文件(恰好是优化的默认文件),看到了两个有趣的部分。
# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {
native <methods>;
}
^ 这个部分应该是确保我的原生函数没有被从二进制中丢弃。为什么会发生这种情况,我仍然不知道。
# Understand the @Keep support annotation.
-keep class android.support.annotation.Keep
^ 这一节让我想到了使用 @Keep
来强制它不丢弃该函数。经过一番测试和确认,事实证明这是一个有效的解决方案。
我会进一步做一些测试,找到收缩器不保留我的原生函数的根本原因,但既然找到了解决方法,我就标记为已解决。希望对以后遇到的人有帮助。