1. nativePtr作用
Java层:nativePtr long类型的 保存 C++ 对象指针的地址
C++层:nativePtr —> C++ 对象
1.1 理解源码中nativePtr 在openCV中有个Mat.java ,Mat.cpp(Java_org_opencv_core_Mat_n_1Mat__DDI)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public class Mat { public final long nativeObj; public Mat (long addr) { if (addr == 0 ) throw new UnsupportedOperationException("Native object address is NULL" ); nativeObj = addr; } public Mat () { nativeObj = n_Mat(); } private static native long n_Mat () ; private static native long n_Mat (int rows, int cols, int type) ; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__DDI (JNIEnv* env, jclass, jdouble size_width, jdouble size_height, jint type); JNIEXPORT jlong JNICALL Java_org_opencv_core_Mat_n_1Mat__DDI (JNIEnv* env, jclass, jdouble size_width, jdouble size_height, jint type) { static const char method_name[] = "Mat::n_1Mat__DDI()" ; try { LOGD("%s" , method_name); Size size ((int )size_width, (int )size_height) ; return (jlong) new Mat( size, type ); } catch (const std ::exception &e) { throwJavaException(env, &e, method_name); } catch (...) { throwJavaException(env, 0 , method_name); } return 0 ; }
结论: Java层拿到nativeObj就是 Native层C++对象的指针,也就是对象的首地址,下次想去使用Native层的功能时,就可以使用首地址寻找C++对象,并让他干活即可。
2. Parcel源码分析 2.1 Parcel初始化流程 java端初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package android.os;public final class Parcel { public static Parcel obtain () { final Parcel[] pool = sOwnedPool; synchronized (pool) { Parcel p; for (int i=0 ; i<POOL_SIZE; i++) { p = pool[i]; if (p != null ) { pool[i] = null ; if (DEBUG_RECYCLE) { p.mStack = new RuntimeException(); } p.mReadWriteHelper = ReadWriteHelper.DEFAULT; return p; } } } return new Parcel(0 ); } }
1 2 3 4 5 6 7 8 9 private Parcel (long nativePtr) { if (DEBUG_RECYCLE) { mStack = new RuntimeException(); } init(nativePtr); }
1 2 3 4 5 6 7 8 9 10 11 private void init (long nativePtr) { if (nativePtr != 0 ) { mNativePtr = nativePtr; mOwnsNativeParcelObject = false ; } else { mNativePtr = nativeCreate(); mOwnsNativeParcelObject = true ; } } private static native long nativeCreate () ;
native代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 static const JNINativeMethod gParcelMethods[] = { ...... {"openFileDescriptor" , "(Ljava/lang/String;I)Ljava/io/FileDescriptor;" , (void *)android_os_Parcel_openFileDescriptor}, {"dupFileDescriptor" , "(Ljava/io/FileDescriptor;)Ljava/io/FileDescriptor;" , (void *)android_os_Parcel_dupFileDescriptor}, {"closeFileDescriptor" , "(Ljava/io/FileDescriptor;)V" , (void *)android_os_Parcel_closeFileDescriptor}, {"nativeCreate" , "()J" , (void *)android_os_Parcel_create}, {"nativeFreeBuffer" , "(J)J" , (void *)android_os_Parcel_freeBuffer}, {"nativeDestroy" , "(J)V" , (void *)android_os_Parcel_destroy}, ...... };
1 2 3 4 5 6 7 8 static jlong android_os_Parcel_create (JNIEnv* env, jclass clazz) { Parcel* parcel = new Parcel(); return reinterpret_cast <jlong>(parcel); }
2.2 写数据 Parcel.java
1 2 3 4 5 6 7 8 9 10 11 12 public final void writeInt (int val) { nativeWriteInt(mNativePtr, val); } @FastNative private static native void nativeWriteInt (long nativePtr, int val) ;
android_os_Parcel.cpp 的 nativeWriteInt:
1 2 3 4 5 6 7 8 9 10 11 {"nativeWriteByteArray" , "(J[BII)V" , (void *)android_os_Parcel_writeByteArray}, {"nativeWriteBlob" , "(J[BII)V" , (void *)android_os_Parcel_writeBlob}, {"nativeWriteInt" , "(JI)V" , (void *)android_os_Parcel_writeInt}, {"nativeWriteLong" , "(JJ)V" , (void *)android_os_Parcel_writeLong}, {"nativeWriteFloat" , "(JF)V" , (void *)android_os_Parcel_writeFloat},
实现函数android_os_Parcel_writeInt :
1 2 3 4 5 6 7 8 9 10 11 12 13 static void android_os_Parcel_writeInt (JNIEnv* env, jclass clazz, jlong nativePtr, jint val) { Parcel* parcel = reinterpret_cast <Parcel*>(nativePtr); if (parcel != NULL ) { const status_t err = parcel->writeInt32(val); if (err != NO_ERROR) { signalExceptionForError(env, clazz, err); } } }
Parcel.cpp 的 writeInt32:
1 2 3 status_t Parcel::writeInt32 (int32_t val) { return writeAligned(val); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 template <class T > status_t Parcel::writeAligned (T val) { COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof (T)) == sizeof (T)); if ((mDataPos+sizeof (val)) <= mDataCapacity) { restart_write: *reinterpret_cast <T*>(mData+mDataPos) = val; return finishWrite(sizeof (val)); } status_t err = growData(sizeof (val)); if (err == NO_ERROR) goto restart_write; return err; }
finsihWrite函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 status_t Parcel::finishWrite (size_t len) { if (len > INT32_MAX) { return BAD_VALUE; } mDataPos += len; ALOGV("finishWrite Setting data pos of %p to %zu" , this , mDataPos); if (mDataPos > mDataSize) { mDataSize = mDataPos; ALOGV("finishWrite Setting data size of %p to %zu" , this , mDataSize); } return NO_ERROR; }
读的流程是一样的,按照顺序一个类型一个类型读出来。最核心的思想就是共享内存写数据和读数据。
2.3 CMakeList配置导入全部.cpp 1 2 3 4 5 6 file(GLOB allSource *.c *.cpp) add_library( native-lib SHARED ${allSource} )
3. 自定义Parcelable 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 public class Student implements Parcelable { protected Student (Parcel in) { in.readInt(); in.readString(); } @Override public void writeToParcel (Parcel dest, int flags) { dest.writeInt(10 ); dest.writeString("AAA" ); } @Override public int describeContents () { return 0 ; } public static final Creator<Student> CREATOR = new Creator<Student>() { @Override public Student createFromParcel (Parcel in) { return new Student(in); } @Override public Student[] newArray(int size) { return new Student[size]; } }; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public class MainActivity extends AppCompatActivity { @Override protected void onCreate (Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); Parcel parcel = Parcel.obtain(); parcel.writeInt(50 ); parcel.writeInt(100 ); parcel.setDataPosition(0 ); int r = parcel.readInt(); Log.d("Jack" , "onCreate: 系统的:" + r); r = parcel.readInt(); Log.d("Jack" , "onCreate: 系统的:" + r); } }
4.Parcelable为什么比Serializable高效 Serializable IO流完成的(存储到磁盘), Parcelable C++ 对象指针 共享内存 指针挪动报错数据。
版权声明: 此文章版权归Jack Ou所有,如有转载,请註明来自原作者