了解导致信号 11 (SIGSEGV)、代码 1 (SEGV_MAPERR) 几秒钟后出错的 Android 问题
Understanding the Android issue causing signal 11 (SIGSEGV), code 1 (SEGV_MAPERR) Error after a few seconds
我是运行传感器和位置服务,数据被传递到TraceManager文件,在那里处理它并传递到TraceCWrapper以映射到共享C库。所以,看来传感器和位置数据正常并在 TraceManager 中接收,然后传递到 TraceCWrapper,但是应用程序在几秒钟后崩溃,我得到的唯一错误行是:
A/libc:致命信号 11 (SIGSEGV),代码 1 (SEGV_MAPERR),tid 29938 (AsyncTask #1) 中的故障地址 0x8,pid 29870 (pp.traceandroid)
public class TraceManager extends AppCompatActivity {
private String TAG = "TraceManager";
private int phoneAngle = 0;
private double initialStepCalibrationOffset;
private int initialPointingAngleDeg = 0;
private int initialAlignmentMode = 0;
private int startingFloorID = 0;
private LatLng startingLatLong;
private double startingAccuracy = 1.0;
private Context context;
private boolean isMagConsistentAtInit = false;
private boolean isMagValid = true;
private Timer callBackTimer;
private String[] contentsStatic;
private String[] contentsDynamic;
private boolean isRunning = false;
private TraceCWrapper traceCWrapper = new TraceCWrapper();
Handler callbackHandler = new Handler();
Runnable callbackRunnable;
//internal use only
private boolean _traceCDontActuallyUse;
// The interval, in seconds, for providing trace updates.
public ObservableDouble updateCallbackInterval = new ObservableDouble(0){
@Override
public void addOnPropertyChangedCallback(@NonNull OnPropertyChangedCallback callback) {
if(isRunning){
stopCallbackTimer();
startCallbackTimer();
}
super.addOnPropertyChangedCallback(callback);
}
};
private double updateCallBackIntervalValue = updateCallbackInterval.get();
/// A Boolean value
public ObservableBoolean allowsBackgroundExecution = new ObservableBoolean(false){
@Override
public void addOnPropertyChangedCallback(@NonNull OnPropertyChangedCallback callback) {
if(isRunning){
stopUpdatingTrace();
startUpdatingTrace();
}
super.addOnPropertyChangedCallback(callback);
}
};
private boolean allowsBackgroundExecutionValue = allowsBackgroundExecution.get();
public TraceManager(Context context){
this.context=context;
}
public TraceManager(){
}
public void initialiseTrace(String[] mapFloors,
String[] initialDynamicMaps,
int phoneRelativeToBodyDegree, //this comes from onboarding?
double updateCallBackIntervalValue,
boolean allowsBackgroundExecutionValue,
double initialStepCalibrationOffset, //standard
String[] iBeaconUUIDs,
int startingFloorID,
LatLng startingLatLong, //this is form the starting node
double startingAccuracy, //
boolean _traceCDontActuallyUse,
int phoneOrientation,
int phoneOrientationUse,
boolean magntometerValid
){
this.contentsStatic = mapFloors;
this.contentsDynamic = initialDynamicMaps;
this.phoneAngle = phoneRelativeToBodyDegree;
this.initialStepCalibrationOffset = initialStepCalibrationOffset;
this.updateCallbackInterval = updateCallbackInterval;
this.allowsBackgroundExecution = allowsBackgroundExecution;
this.isMagValid = magntometerValid;
if(!(iBeaconUUIDs.length <=0)){
LocationProvider.arrayOfUUIDsToDetect = iBeaconUUIDs;
}else{
Log.i(TAG, "TraceManager.init: ignoring ibeaconUIDs, because it is empty. Default used");
};
this.startingFloorID = startingFloorID;
this.startingLatLong = startingLatLong;
this.startingAccuracy = startingAccuracy;
this.initialPointingAngleDeg = phoneOrientation;
this.initialAlignmentMode = phoneOrientationUse;
//internal use only
this._traceCDontActuallyUse = _traceCDontActuallyUse;
}
//Functions
/// Broadcast Receiver to get readings from MotionProvider/service
public void startUpdatingSensors(){
//Start sensor service
Intent startService = new Intent(TraceManager.this, SensorService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(startService);
} else {
startService(startService);
}
}
/// Starts the generation of trace updates.
public void startUpdatingTrace(){
//Start Sensors
//startUpdatingSensors();
//register for sensorBroadcast
BroadcastReceiver sensorReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "imu Received");
TCIMUEvent tcimuEvent = (TCIMUEvent) intent.getSerializableExtra("imu");
traceCWrapper.provideDeviceMotion(tcimuEvent, 1, 90, RotationMode.PortraitYUp);
}
};
LocalBroadcastManager.getInstance(context).registerReceiver(
sensorReceiver, new IntentFilter("imuCreated")
);
//register for locationBroadcast
//register for sensorBroadcast
BroadcastReceiver locationReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "location Received");
TCLocationEvent tcLocationEvent = (TCLocationEvent) intent.getSerializableExtra("locationCreated");
Log.d(TAG, "Inlocation reciever");
traceCWrapper.provideLocation(tcLocationEvent);
}
};
LocalBroadcastManager.getInstance(context).registerReceiver(
locationReceiver, new IntentFilter("locationCreated")
);
Log.d(TAG, "inside updating trace");
//Start CallbackTimer
startCallbackTimer();
}
private void CallbackUpdate() {
/* callbackRunnable = new Runnable(){
@Override
public void run() {
Log.d(TAG, "calling callback");
traceCWrapper.getLatestTraceResult();
callbackHandler.postDelayed(this, 1000);
}
};*/
}
private void startCallbackTimer(){
Log.d(TAG, "I get in here callback");
callbackRunnable = new Runnable(){
@Override
public void run() {
Log.d(TAG, "calling callback");
traceCWrapper.getLatestTraceResult();
callbackHandler.postDelayed(this, 1000);
}
};
callbackHandler.postDelayed(callbackRunnable, 1000);
}
private void stopCallbackTimer(){
callbackHandler.removeCallbacks(callbackRunnable);
}
//Calls TraceCWrapper upadate maps and passes the dynamic maps
/* public void updateMaps(String[] dynamicMaps){
traceCWrapper.updateMaps(dynamicMaps dynamicmaps){
}
}*/
public void stopUpdatingTrace(){
boolean stopSensors = true;
if(stopSensors){
stopUpdatingSensors();
}
//Callback Timer
stopCallbackTimer();
//State
isRunning = false;
//Trace terminate
if (_traceCDontActuallyUse == false){
traceCWrapper.terminate();
}
}
private void stopUpdatingSensors() {
//todo
//stop the event bus
//stop the service
}
@RequiresApi(api = Build.VERSION_CODES.O)
public void provideManualLocation(TraceManualLocation manualLocation){
if(isRunning){
}else{
Log.e(TAG, "Calling provideManualLocation, but is running is set to false");
}
if(!_traceCDontActuallyUse){
traceCWrapper.provideManualLocation(manualLocation);
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
public void provideManualHeadingCorrection(TraceManualHeading traceManualHeading){
if(isRunning){
}else{
Log.e(TAG, "Calling provideHeadingCorrection, but is running is set to false");
}
if (!_traceCDontActuallyUse){
traceCWrapper.provideManualHeading(traceManualHeading);
}
}
public void updateParameter(TraceCVarParameter traceCVarParameter, double value){
if(isRunning){
}else{
Log.e(TAG, "Calling updateparameter, but is running is set to false");
}
//todo
//callback async
}
//Private [START]
boolean isInitialised = false;
public boolean isInitialised() {
if(!isInitialised){
}else{
//todo
//send to didfinishinitialisation? confirm isMagConsistentAtInit is true
}
return isInitialised;
}
private boolean isMagConsistantAtInit = false;
private Timer callbackTimer;
/* public traceCallBack(int seconds){
callBackTimer = new Timer();
callBackTimer.schedule(new callUpdate(), seconds*1000);
}*/
class callUpdate extends TimerTask{
@Override
public void run() {
//traceCWrapper.getLatestTraceResult();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_trace_manager);
}
}
我没有足够的空间来添加 TraceCWrapper 文件,但是库加载为:
static CLibrary lib = Native.loadLibrary("com.waymap.app.traceandroid", CLibrary.class);
作为主要示例,方法 traceCWrapper.provideDeviceMotion() 在 TraceCWrapper 中接收为:
//Provide Device Motion
public static boolean provideDeviceMotion(TCIMUEvent mTCIMUEvent, int Status, double userHeadingDeg, float rotationMode){
DeviceMotion dM = new DeviceMotion();
dM.setTcimuEvent(mTCIMUEvent);
dM.setStatus(Status);
dM.setUserHeadingDeg(userHeadingDeg);
dM.setRotationMode(rotationMode);
if(isRunning) {
new sendToTraceHandleImuEvent().execute(dM);
isInitalized = true;
return isInitalized;
}else{
Log.i(TAG, "IMU update ignored as not running");
isInitalized = false;
return isInitalized;
}
}
public static class sendToTraceHandleImuEvent extends AsyncTask<DeviceMotion,Void,Void>{
@Override
protected Void doInBackground(DeviceMotion... devicemotions) {
/*public class Arg extends Structure {
public devicemotions[] var1 = new byte[9];
public devicemotions[] var2 = new byte[5];
}*/
Log.d(TAG, "InTraceCwrapper Again, provideIMU");
lib.TraceHandleImuEvent(devicemotions[0].getTcimuEvent(), devicemotions[0].getStatus(), devicemotions[0].getUserHeadingDeg(), devicemotions[0].getRotationMode());
return null;
}
}
您将不得不原谅大量的日志记录和多余的代码,因为我已经为此苦苦挣扎了一段时间。
传递我的 TCIMUEvent 时,我正在使用如下结构注释:
@Structure.FieldOrder({ "time", "accel", "accelValid", "mag", "magValid", "gyro", "gyroValid", "pressure", "pressureValid", "temperature", "temperatureValid"})
public class TCIMUEvent extends Structure implements Serializable {
public double time;
public float[] accel = new float[3];
public boolean accelValid;
public float[] mag = new float[3];
public boolean magValid;
public float[] gyro = new float[3];
public boolean gyroValid;
public float pressure;
public boolean pressureValid;
public float temperature;
public boolean temperatureValid;
public TCIMUEvent(double time, float[] accel, boolean accelValid, float[] mag, boolean magValid, float[] gyro, boolean gyroValid, float pressure, boolean pressureValid, float temperature, boolean temperatureValid) {
this.time = time;
this.accel = accel;
this.accelValid = accelValid;
this.mag = mag;
this.magValid = magValid;
this.gyro = gyro;
this.gyroValid = gyroValid;
this.pressure = pressure;
this.pressureValid = pressureValid;
this.temperature = temperature;
this.temperatureValid = temperatureValid;
}
}
需要的 Java C 映射:
My Java Library to map:
void TracehandleLocationEvent(TCLocationEvent tcLocationEvent);
void TracehandleManualLocationEvent(TCManualLocationEvent tcManualLocationEvent);
void TracehandleManualHeadingEvent(TCManualHeadingEvent tcManualHeadingEvent);
void TracehandleManualInitialLocation(TCLocationEvent initialLocationEvent);
void TraceHandleImuEvent(TCIMUEvent tcimuEvent, int Status, double userHeadingDeg, float rotationMode);
void TraceGetResult(Double uptime, Pointer traceResult_out);
-------- These map retrospectively to C:---------
void TraceHandleLocationEvent (const Trace_locationSample_t *locationSample)
void TraceHandleManualLocationEvent(const Trace_manualLocationSample_t
*manualLocationSample)
void TraceHandleManualHeadingEvent(const Trace_manualHeadingSample_t
*manualHeadingSample)
void TraceHandleLocationEvent (const Trace_locationSample_t *locationSample)
void TraceHandleImuEvent(Trace_imuDataSample_t *imuDataSample, int *status,
double *userHeadingDeg, StrapdownStreaming_RotationMode *currentRotateMode)
void TraceGetResult(double time, Trace_Result_t *TraceResult)
新的Mappings是这样的,对象的结构和原题中的格式一样:
void TracehandleLocationEvent(TCLocationEvent tcLocationEvent);
void TracehandleManualLocationEvent(TCManualLocationEvent tcManualLocationEvent);
void TracehandleManualHeadingEvent(TCManualHeadingEvent tcManualHeadingEvent);
void TracehandleManualInitialLocation(TCLocationEvent initialLocationEvent);
void TraceGetResult(DoubleByReference uptime, TCResult traceResult_out);
void TraceHandleImuEvent(TCIMUEvent tcimuEvent, IntByReference status, DoubleByReference heading, FloatByReference rotationMode);
现在抛出的错误与我的 Structure 对象中的空构造函数有关:
java.lang.Error: Structure.getFieldOrder() on class com.dataTypes.TCLocationEvent returns names ([altitude, coordinate, horizontalAccuracy, timestamp, verticalAccuracy]) which do not match declared field names ([])
at com.sun.jna.Structure.getFields(Structure.java:1089)
at com.sun.jna.Structure.deriveLayout(Structure.java:1232)
at com.sun.jna.Structure.calculateSize(Structure.java:1159)
at com.sun.jna.Structure.calculateSize(Structure.java:1111)
at com.sun.jna.Structure.allocateMemory(Structure.java:414)
at com.sun.jna.Structure.<init>(Structure.java:205)
at com.sun.jna.Structure.<init>(Structure.java:193)
at com.sun.jna.Structure.<init>(Structure.java:180)
at com.sun.jna.Structure.<init>(Structure.java:172)
at com.dataTypes.TCLocationEvent.<init>(TCLocationEvent.java:30)
at com.locationGetter.LocationService.<clinit>(LocationService.java:39)
JNA 映射的 SIGSEGV 错误通常是由访问不属于您的本机内存引起的。问题各不相同,但首先要看的是结构类型映射和 method/function 参数映射。
作为一个具体示例(可能还有更多),您的代码包含此映射:
void TraceHandleImuEvent(TCIMUEvent tcimuEvent, int Status,
double userHeadingDeg, float rotationMode);
但是,本机映射不希望此处出现 int
、double
和 float
。它需要指针:
void TraceHandleImuEvent(Trace_imuDataSample_t *imuDataSample, int *status,
double *userHeadingDeg, StrapdownStreaming_RotationMode *currentRotateMode)
(像 TCIMUEvent
这样的结构在作为参数传递时会自动映射到它们的指针,所以没关系。)
正在发生的事情是您正在传递 int
状态(例如 8),但本机代码正在考虑 "There's an integer stored at memory location 0x8
." 您不拥有该内存,因此出现错误。
IntByReference
是正确的类型映射,对于许多函数参数也是如此。
我是运行传感器和位置服务,数据被传递到TraceManager文件,在那里处理它并传递到TraceCWrapper以映射到共享C库。所以,看来传感器和位置数据正常并在 TraceManager 中接收,然后传递到 TraceCWrapper,但是应用程序在几秒钟后崩溃,我得到的唯一错误行是:
A/libc:致命信号 11 (SIGSEGV),代码 1 (SEGV_MAPERR),tid 29938 (AsyncTask #1) 中的故障地址 0x8,pid 29870 (pp.traceandroid)
public class TraceManager extends AppCompatActivity {
private String TAG = "TraceManager";
private int phoneAngle = 0;
private double initialStepCalibrationOffset;
private int initialPointingAngleDeg = 0;
private int initialAlignmentMode = 0;
private int startingFloorID = 0;
private LatLng startingLatLong;
private double startingAccuracy = 1.0;
private Context context;
private boolean isMagConsistentAtInit = false;
private boolean isMagValid = true;
private Timer callBackTimer;
private String[] contentsStatic;
private String[] contentsDynamic;
private boolean isRunning = false;
private TraceCWrapper traceCWrapper = new TraceCWrapper();
Handler callbackHandler = new Handler();
Runnable callbackRunnable;
//internal use only
private boolean _traceCDontActuallyUse;
// The interval, in seconds, for providing trace updates.
public ObservableDouble updateCallbackInterval = new ObservableDouble(0){
@Override
public void addOnPropertyChangedCallback(@NonNull OnPropertyChangedCallback callback) {
if(isRunning){
stopCallbackTimer();
startCallbackTimer();
}
super.addOnPropertyChangedCallback(callback);
}
};
private double updateCallBackIntervalValue = updateCallbackInterval.get();
/// A Boolean value
public ObservableBoolean allowsBackgroundExecution = new ObservableBoolean(false){
@Override
public void addOnPropertyChangedCallback(@NonNull OnPropertyChangedCallback callback) {
if(isRunning){
stopUpdatingTrace();
startUpdatingTrace();
}
super.addOnPropertyChangedCallback(callback);
}
};
private boolean allowsBackgroundExecutionValue = allowsBackgroundExecution.get();
public TraceManager(Context context){
this.context=context;
}
public TraceManager(){
}
public void initialiseTrace(String[] mapFloors,
String[] initialDynamicMaps,
int phoneRelativeToBodyDegree, //this comes from onboarding?
double updateCallBackIntervalValue,
boolean allowsBackgroundExecutionValue,
double initialStepCalibrationOffset, //standard
String[] iBeaconUUIDs,
int startingFloorID,
LatLng startingLatLong, //this is form the starting node
double startingAccuracy, //
boolean _traceCDontActuallyUse,
int phoneOrientation,
int phoneOrientationUse,
boolean magntometerValid
){
this.contentsStatic = mapFloors;
this.contentsDynamic = initialDynamicMaps;
this.phoneAngle = phoneRelativeToBodyDegree;
this.initialStepCalibrationOffset = initialStepCalibrationOffset;
this.updateCallbackInterval = updateCallbackInterval;
this.allowsBackgroundExecution = allowsBackgroundExecution;
this.isMagValid = magntometerValid;
if(!(iBeaconUUIDs.length <=0)){
LocationProvider.arrayOfUUIDsToDetect = iBeaconUUIDs;
}else{
Log.i(TAG, "TraceManager.init: ignoring ibeaconUIDs, because it is empty. Default used");
};
this.startingFloorID = startingFloorID;
this.startingLatLong = startingLatLong;
this.startingAccuracy = startingAccuracy;
this.initialPointingAngleDeg = phoneOrientation;
this.initialAlignmentMode = phoneOrientationUse;
//internal use only
this._traceCDontActuallyUse = _traceCDontActuallyUse;
}
//Functions
/// Broadcast Receiver to get readings from MotionProvider/service
public void startUpdatingSensors(){
//Start sensor service
Intent startService = new Intent(TraceManager.this, SensorService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(startService);
} else {
startService(startService);
}
}
/// Starts the generation of trace updates.
public void startUpdatingTrace(){
//Start Sensors
//startUpdatingSensors();
//register for sensorBroadcast
BroadcastReceiver sensorReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "imu Received");
TCIMUEvent tcimuEvent = (TCIMUEvent) intent.getSerializableExtra("imu");
traceCWrapper.provideDeviceMotion(tcimuEvent, 1, 90, RotationMode.PortraitYUp);
}
};
LocalBroadcastManager.getInstance(context).registerReceiver(
sensorReceiver, new IntentFilter("imuCreated")
);
//register for locationBroadcast
//register for sensorBroadcast
BroadcastReceiver locationReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "location Received");
TCLocationEvent tcLocationEvent = (TCLocationEvent) intent.getSerializableExtra("locationCreated");
Log.d(TAG, "Inlocation reciever");
traceCWrapper.provideLocation(tcLocationEvent);
}
};
LocalBroadcastManager.getInstance(context).registerReceiver(
locationReceiver, new IntentFilter("locationCreated")
);
Log.d(TAG, "inside updating trace");
//Start CallbackTimer
startCallbackTimer();
}
private void CallbackUpdate() {
/* callbackRunnable = new Runnable(){
@Override
public void run() {
Log.d(TAG, "calling callback");
traceCWrapper.getLatestTraceResult();
callbackHandler.postDelayed(this, 1000);
}
};*/
}
private void startCallbackTimer(){
Log.d(TAG, "I get in here callback");
callbackRunnable = new Runnable(){
@Override
public void run() {
Log.d(TAG, "calling callback");
traceCWrapper.getLatestTraceResult();
callbackHandler.postDelayed(this, 1000);
}
};
callbackHandler.postDelayed(callbackRunnable, 1000);
}
private void stopCallbackTimer(){
callbackHandler.removeCallbacks(callbackRunnable);
}
//Calls TraceCWrapper upadate maps and passes the dynamic maps
/* public void updateMaps(String[] dynamicMaps){
traceCWrapper.updateMaps(dynamicMaps dynamicmaps){
}
}*/
public void stopUpdatingTrace(){
boolean stopSensors = true;
if(stopSensors){
stopUpdatingSensors();
}
//Callback Timer
stopCallbackTimer();
//State
isRunning = false;
//Trace terminate
if (_traceCDontActuallyUse == false){
traceCWrapper.terminate();
}
}
private void stopUpdatingSensors() {
//todo
//stop the event bus
//stop the service
}
@RequiresApi(api = Build.VERSION_CODES.O)
public void provideManualLocation(TraceManualLocation manualLocation){
if(isRunning){
}else{
Log.e(TAG, "Calling provideManualLocation, but is running is set to false");
}
if(!_traceCDontActuallyUse){
traceCWrapper.provideManualLocation(manualLocation);
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
public void provideManualHeadingCorrection(TraceManualHeading traceManualHeading){
if(isRunning){
}else{
Log.e(TAG, "Calling provideHeadingCorrection, but is running is set to false");
}
if (!_traceCDontActuallyUse){
traceCWrapper.provideManualHeading(traceManualHeading);
}
}
public void updateParameter(TraceCVarParameter traceCVarParameter, double value){
if(isRunning){
}else{
Log.e(TAG, "Calling updateparameter, but is running is set to false");
}
//todo
//callback async
}
//Private [START]
boolean isInitialised = false;
public boolean isInitialised() {
if(!isInitialised){
}else{
//todo
//send to didfinishinitialisation? confirm isMagConsistentAtInit is true
}
return isInitialised;
}
private boolean isMagConsistantAtInit = false;
private Timer callbackTimer;
/* public traceCallBack(int seconds){
callBackTimer = new Timer();
callBackTimer.schedule(new callUpdate(), seconds*1000);
}*/
class callUpdate extends TimerTask{
@Override
public void run() {
//traceCWrapper.getLatestTraceResult();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_trace_manager);
}
}
我没有足够的空间来添加 TraceCWrapper 文件,但是库加载为:
static CLibrary lib = Native.loadLibrary("com.waymap.app.traceandroid", CLibrary.class);
作为主要示例,方法 traceCWrapper.provideDeviceMotion() 在 TraceCWrapper 中接收为:
//Provide Device Motion
public static boolean provideDeviceMotion(TCIMUEvent mTCIMUEvent, int Status, double userHeadingDeg, float rotationMode){
DeviceMotion dM = new DeviceMotion();
dM.setTcimuEvent(mTCIMUEvent);
dM.setStatus(Status);
dM.setUserHeadingDeg(userHeadingDeg);
dM.setRotationMode(rotationMode);
if(isRunning) {
new sendToTraceHandleImuEvent().execute(dM);
isInitalized = true;
return isInitalized;
}else{
Log.i(TAG, "IMU update ignored as not running");
isInitalized = false;
return isInitalized;
}
}
public static class sendToTraceHandleImuEvent extends AsyncTask<DeviceMotion,Void,Void>{
@Override
protected Void doInBackground(DeviceMotion... devicemotions) {
/*public class Arg extends Structure {
public devicemotions[] var1 = new byte[9];
public devicemotions[] var2 = new byte[5];
}*/
Log.d(TAG, "InTraceCwrapper Again, provideIMU");
lib.TraceHandleImuEvent(devicemotions[0].getTcimuEvent(), devicemotions[0].getStatus(), devicemotions[0].getUserHeadingDeg(), devicemotions[0].getRotationMode());
return null;
}
}
您将不得不原谅大量的日志记录和多余的代码,因为我已经为此苦苦挣扎了一段时间。
传递我的 TCIMUEvent 时,我正在使用如下结构注释:
@Structure.FieldOrder({ "time", "accel", "accelValid", "mag", "magValid", "gyro", "gyroValid", "pressure", "pressureValid", "temperature", "temperatureValid"})
public class TCIMUEvent extends Structure implements Serializable {
public double time;
public float[] accel = new float[3];
public boolean accelValid;
public float[] mag = new float[3];
public boolean magValid;
public float[] gyro = new float[3];
public boolean gyroValid;
public float pressure;
public boolean pressureValid;
public float temperature;
public boolean temperatureValid;
public TCIMUEvent(double time, float[] accel, boolean accelValid, float[] mag, boolean magValid, float[] gyro, boolean gyroValid, float pressure, boolean pressureValid, float temperature, boolean temperatureValid) {
this.time = time;
this.accel = accel;
this.accelValid = accelValid;
this.mag = mag;
this.magValid = magValid;
this.gyro = gyro;
this.gyroValid = gyroValid;
this.pressure = pressure;
this.pressureValid = pressureValid;
this.temperature = temperature;
this.temperatureValid = temperatureValid;
}
}
需要的 Java C 映射:
My Java Library to map:
void TracehandleLocationEvent(TCLocationEvent tcLocationEvent);
void TracehandleManualLocationEvent(TCManualLocationEvent tcManualLocationEvent);
void TracehandleManualHeadingEvent(TCManualHeadingEvent tcManualHeadingEvent);
void TracehandleManualInitialLocation(TCLocationEvent initialLocationEvent);
void TraceHandleImuEvent(TCIMUEvent tcimuEvent, int Status, double userHeadingDeg, float rotationMode);
void TraceGetResult(Double uptime, Pointer traceResult_out);
-------- These map retrospectively to C:---------
void TraceHandleLocationEvent (const Trace_locationSample_t *locationSample)
void TraceHandleManualLocationEvent(const Trace_manualLocationSample_t
*manualLocationSample)
void TraceHandleManualHeadingEvent(const Trace_manualHeadingSample_t
*manualHeadingSample)
void TraceHandleLocationEvent (const Trace_locationSample_t *locationSample)
void TraceHandleImuEvent(Trace_imuDataSample_t *imuDataSample, int *status,
double *userHeadingDeg, StrapdownStreaming_RotationMode *currentRotateMode)
void TraceGetResult(double time, Trace_Result_t *TraceResult)
新的Mappings是这样的,对象的结构和原题中的格式一样:
void TracehandleLocationEvent(TCLocationEvent tcLocationEvent);
void TracehandleManualLocationEvent(TCManualLocationEvent tcManualLocationEvent);
void TracehandleManualHeadingEvent(TCManualHeadingEvent tcManualHeadingEvent);
void TracehandleManualInitialLocation(TCLocationEvent initialLocationEvent);
void TraceGetResult(DoubleByReference uptime, TCResult traceResult_out);
void TraceHandleImuEvent(TCIMUEvent tcimuEvent, IntByReference status, DoubleByReference heading, FloatByReference rotationMode);
现在抛出的错误与我的 Structure 对象中的空构造函数有关:
java.lang.Error: Structure.getFieldOrder() on class com.dataTypes.TCLocationEvent returns names ([altitude, coordinate, horizontalAccuracy, timestamp, verticalAccuracy]) which do not match declared field names ([])
at com.sun.jna.Structure.getFields(Structure.java:1089)
at com.sun.jna.Structure.deriveLayout(Structure.java:1232)
at com.sun.jna.Structure.calculateSize(Structure.java:1159)
at com.sun.jna.Structure.calculateSize(Structure.java:1111)
at com.sun.jna.Structure.allocateMemory(Structure.java:414)
at com.sun.jna.Structure.<init>(Structure.java:205)
at com.sun.jna.Structure.<init>(Structure.java:193)
at com.sun.jna.Structure.<init>(Structure.java:180)
at com.sun.jna.Structure.<init>(Structure.java:172)
at com.dataTypes.TCLocationEvent.<init>(TCLocationEvent.java:30)
at com.locationGetter.LocationService.<clinit>(LocationService.java:39)
JNA 映射的 SIGSEGV 错误通常是由访问不属于您的本机内存引起的。问题各不相同,但首先要看的是结构类型映射和 method/function 参数映射。
作为一个具体示例(可能还有更多),您的代码包含此映射:
void TraceHandleImuEvent(TCIMUEvent tcimuEvent, int Status,
double userHeadingDeg, float rotationMode);
但是,本机映射不希望此处出现 int
、double
和 float
。它需要指针:
void TraceHandleImuEvent(Trace_imuDataSample_t *imuDataSample, int *status,
double *userHeadingDeg, StrapdownStreaming_RotationMode *currentRotateMode)
(像 TCIMUEvent
这样的结构在作为参数传递时会自动映射到它们的指针,所以没关系。)
正在发生的事情是您正在传递 int
状态(例如 8),但本机代码正在考虑 "There's an integer stored at memory location 0x8
." 您不拥有该内存,因此出现错误。
IntByReference
是正确的类型映射,对于许多函数参数也是如此。