更新2017-05-17.我不再为出现此问题的公司工作,也无法访问Delphi XEx.当我在那里时,问题通过迁移到混合FPC + GCC(Pascal + C)来解决,NEON内在函数用于某些例程,它们有所不同.(强烈建议使用FPC + GCC,因为它可以使用标准工具,特别是Valgrind.)如果有人能够通过可靠的示例演示他们如何实际能够从Delphi XEx生成优化的ARM代码,我很高兴接受答案.
Embarcadero的Delphi编译器使用LLVM后端为Android设备生成本机ARM代码.我有大量的Pascal代码需要编译到Android应用程序中,我想知道如何使Delphi生成更高效的代码.现在,我甚至都没有谈论自动SIMD优化等高级功能,只是关于生成合理的代码.当然必须有一种方法将参数传递给LLVM端,或以某种方式影响结果?通常,任何编译器都会有很多选项来影响代码编译和优化,但是Delphi的ARM目标似乎只是"优化开/关"就是这样.
LLVM应该能够产生合理紧密且合理的代码,但似乎Delphi以一种奇怪的方式使用它的设施.Delphi希望非常频繁地使用堆栈,它通常只利用处理器的寄存器r0-r3作为临时变量.也许是最疯狂的,似乎是将正常的32位整数加载为四个1字节的加载操作.如何让Delphi产生更好的ARM代码,而且没有逐字节麻烦的Android?
起初我认为逐字节加载是用于从big-endian交换字节顺序,但事实并非如此,它实际上只是加载一个带有4个单字节加载的32位数字.*可能是加载完整的32位而不进行未对齐的字大小的内存加载.(是否应该避免这是另一回事,这将暗示整个事情是编译器错误)*
让我们来看看这个简单的函数:
function ReadInteger(APInteger : PInteger) : Integer;
begin
Result := APInteger^;
end;
Run Code Online (Sandbox Code Playgroud)
即使启用了优化,带有更新包1的Delphi XE7以及XE6也会为该功能生成以下ARM汇编代码:
Disassembly of section .text._ZN16Uarmcodetestform11ReadIntegerEPi:
00000000 <_ZN16Uarmcodetestform11ReadIntegerEPi>:
0: b580 push {r7, lr}
2: 466f mov r7, sp
4: b083 sub sp, #12
6: 9002 str r0, [sp, #8]
8: 78c1 ldrb r1, [r0, #3]
a: 7882 ldrb r2, [r0, #2]
c: ea42 2101 orr.w r1, r2, r1, lsl #8
10: 7842 ldrb r2, [r0, #1] …Run Code Online (Sandbox Code Playgroud) 我一直在阅读有关追踪SIGSEGVAndroid应用程序的原因的其他帖子.我打算在我的应用程序中搜索与Canvas使用相关的可能的NullPointers,但我的SIGSEGVbarf每次都有不同的内存地址.另外我见过code=1和code=2.如果内存地址是0x00000000,我有一个线索它是一个NullPointer.
我得到的最后一个是code=2:
A/libc(4969): Fatal signal 11 (SIGSEGV) at 0x42a637d9 (code=2)
Run Code Online (Sandbox Code Playgroud)
有关如何追踪此问题的任何建议?
我有一个嫌疑人,但我还没有热衷于尝试它.我的应用程序使用OSMDroid API进行离线映射.OverlayItem类表示地图上的标记/节点.我有一个服务,它通过网络收集数据以填充OverlayItem,然后显示在地图上.为了简化我的设计,我将OverlayItem扩展到我自己的NodeOverlayItem类中,该类包含我在UI Activity和Service中使用的一些附加属性.这给了我UI和服务的单点项目信息.我使用Intents广播到Activity,以便在更改内容时刷新UI映射.Activity绑定到Service,并且有一个Service方法来获取NodeOverlayItem的列表.我认为可能是OSMDroid API使用OverlayItem,而我的服务同时更新节点信息.(并发问题)
在我写这篇文章时,我认为这确实是问题所在.令人头疼的是没有从NodeOverlayItem拆分Node和OverlayItem,而是Activity需要来自Node的一些数据,服务保存.另外,当创建Activity(onResume等等)时,需要从活动离开时服务一直维护的Node数据重新创建OverlayItem对象.例如,您启动应用程序,服务收集数据,UI显示数据,您转到主页,然后返回应用程序,活动将需要从最新的服务节点数据中提取并重新创建OverlayItem.
我知道这不是一个很好或明确的问题.这就像我所有的SO问题都是利基或模糊.如果有人对如何解释这些SIGSEGV错误有任何建议,我们将不胜感激!
更新 这是调试会话期间捕获的最新崩溃.我有3个这样的设备用于测试,当我开发和测试时,它们并不都可靠地崩溃.我添加了一些额外的内容,因此可以注意到GC日志记录.您可以看到问题可能与内存耗尽无关.
03-03 02:02:38.328: I/CommService(7477): Received packet from: 192.168.1.102
03-03 02:02:38.328: I/CommService(7477): Already processed this packet. It's a re-broadcast from another node, or from myself. It's not a repeat broadcast though.
03-03 02:02:38.406: D/CommService(7477): Checking OLSRd info...
03-03 02:02:38.460: D/CommService(7477): Monitoring nodes...
03-03 02:02:38.515: D/dalvikvm(7477): GC_CONCURRENT freed 2050K, 16% …Run Code Online (Sandbox Code Playgroud) 我想使用gradel(gradlew clean build)编译一个开源的android项目(Netguard )但是我遇到了这个错误:
A problem occurred configuring project ':app'.
> Exception thrown while executing model rule: NdkComponentModelPlugin.Rules#cre
ateToolchains
> No toolchains found in the NDK toolchains folder for ABI with prefix: llvm
Run Code Online (Sandbox Code Playgroud)
我打破了,但没有找到帮助的东西.这是主要的build.gradle:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle-experimental:0.6.0-alpha1'
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Run Code Online (Sandbox Code Playgroud)
这里是build.gradle对的app项目:
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion …Run Code Online (Sandbox Code Playgroud) 更新到Android Gradle 插件 3.6.0(2020 年 2 月 24 日发布)后,几个项目独立开始失败:
No version of NDK matched the requested version 20.0.5594570. Versions available locally: 21.0.6113669
Run Code Online (Sandbox Code Playgroud)
通过安装较旧的预期 ndk 版本在本地“修复”此问题非常简单:
sdkmanager 'ndk;20.0.5594570'
Run Code Online (Sandbox Code Playgroud)
但是,我的问题是:这个旧版本在哪里以及如何指定?以及如何更新它以使其与最新版本匹配21.0.6113669?
android android-ndk android-sdk-tools android-gradle-plugin android-sdk-manager
有谁知道我在哪里可以找到旧版本的Android NDK?我们的代码不是用r6构建的.当然必须存在某个存档版本.
我对这整个Gradle和Android Studio支持都很陌生.我已设法使用导出选项将我的android项目转换为gradle.
但我正在寻找一些文档或开始如何将NDK构建集成到gradle构建过程中.
如果可能的话,我还需要某种"后"阶段,将构建二进制文件(.so文件)复制到资产目录.
在我当前的项目中,我使用了多个.so文件.这些位于armeabi和armeabi-v7a文件夹中.不幸的是,其中一个.so文件是6MB,我需要减小文件大小.我想使用armeabi文件并删除armeabi-v7a文件夹,而不是有一个胖的APK文件.
根据NDK文档,armeabi-v7a代码是扩展的armeabi代码,可以包含额外的CPU指令.这一切都超出了我的专业知识,但我怀疑为什么人们想要同时拥有armeabi-v7a和armeabi代码.两者都有充分的理由,对吗?
在我的测试设备上,这一切看起来都很好.这些都有ARM v7 CPU.假设现在一切正常可以安全吗?
我目前正在开展一个项目,我必须使用纯粹的原生ndk.当我尝试从Irrlicht引擎源运行helloworld示例时,它工作正常.然后我尝试在我的项目中使用它,遵循该示例的相同格式.但我得到了:
03-14 01:40:05.308: E/AndroidRuntime(799): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.irrlicht.example1/android.app.POMActivity}: java.lang.ClassNotFoundException: Didn't find class "android.app.POMActivity" on path: DexPathList[[zip file "/data/app/com.irrlicht.example1-2.apk"],nativeLibraryDirectories=[/data/app-lib/com.irrlicht.example1-2, /system/lib]]
Run Code Online (Sandbox Code Playgroud)
在运行我的项目时.
这是我的main.cpp文件:
#include <android/log.h>
#include <jni.h>
#include <android_native_app_glue.h>
#include "android_tools.h"
#ifdef _IRR_ANDROID_PLATFORM_
void android_main(android_app* app)
{
__android_log_print(4 , "pom" , "nothing");
}
Run Code Online (Sandbox Code Playgroud)
#万一
在Android.mk中:
LOCAL_PATH := $(call my-dir)/..
IRRLICHT_PROJECT_PATH := $(LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_MODULE := Irrlicht
LOCAL_SRC_FILES := /home/karthik/Android/Essentials/ogl-es/lib/Android/libIrrlicht.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := HelloWorldMobile1
LOCAL_CFLAGS := -D_IRR_ANDROID_PLATFORM_ -pipe -fno-exceptions -fno-rtti -fstrict-aliasing
LOCAL_C_INCLUDES := -I ../../include -I /home/karthik/Android/Essentials/ogl-es/include …Run Code Online (Sandbox Code Playgroud) 我的make文件有什么问题?
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := foo
LOCAL_SRC_FILES := foo.c
LOCAL_EXPORT_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
Run Code Online (Sandbox Code Playgroud)
foo.c的
#include <string.h>
#include <jni.h>
#include <android/log.h>
#define LOG_TAG "foo"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
void test() {
LOGI("test");
}
Run Code Online (Sandbox Code Playgroud)
NDK建造
foo.c:9: undefined reference to `__android_log_print'
Run Code Online (Sandbox Code Playgroud) 我正在将一个项目转移到新的Android Native Development Kit(即JNI),我想抓住SIGSEGV,如果它发生(可能还有SIGILL,SIGABRT,SIGFPE),以便提供一个很好的崩溃报告对话框,而不是(或之前)当前发生的事情:该过程立即毫不客气地死亡,并且可能是操作系统重启它的一些尝试.(编辑: JVM/Dalvik VM捕获信号并记录堆栈跟踪和其他有用信息;我只是想为用户提供将该信息真正通过电子邮件发送给我的选项.)
情况是:我没有编写的大量C代码完成了这个应用程序中的大部分工作(所有游戏逻辑),虽然它在很多其他平台上都经过了很好的测试,但我完全有可能在我的Android中端口,将它提供垃圾并导致本机代码崩溃,所以我想要当前显示在Android日志中的崩溃转储(本机和Java)(我想在非Android情况下它将是stderr).我可以随意修改C和Java代码,尽管回调(进入和退出JNI)的数量大约为40,显然,小差异的奖励积分.
我听说过J2SE中的信号链接库,libjsig.so,如果我可以在Android上安全地安装这样的信号处理程序,这将解决我的问题的捕捉部分,但我看不到Android/Dalvik这样的库.
java-native-interface android signals segmentation-fault android-ndk