ksnowlv

回顾过去,总结以往;立足现在,铭记当下;技术为主,笔记而已.

Python筛选目录下非jpeg,png,bmp格式的图片

| Comments

功能:筛选指定目录下非jpeg/png/bmp格式的文件,并把路径以日志形式输出。

关键有两点:

  • 目录遍历,记录所有文件路径。
  • 遍历路径,使用imghdr.what判断文件格式,非jpeg/png/bmp格式的文件路径输出。

python3.0实现如下:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import os
import imghdr

##工具功能:筛选目录下非jpeg,png,bmp格式的图片,并输出其路径
##Python 3.0

#图片文件夹目录
IMAGEPATH = None

#初始化
def init():
    global IMAGEPATH
    IMAGEPATH  = "/Users/ksnowlv/Documents/image"


# 功能:读取指定目录下的所有文件绝对路径(包括该目录下所有子目录),并以列表形式返回

def readDir(dirPath):
    myDirPath = dirPath
    if dirPath.endswith('/'):# 要求传入的路径参数最后不能有斜杠,目的是为了递归时格式统一
        myDirPath = dirPath.rstrip('/')
        print('文件夹路径末尾删除/ = %s'%(myDirPath))

    allFiles = []

    if os.path.isdir(myDirPath):
        fileList = os.listdir(myDirPath)
        for f in fileList:
            f = myDirPath+'/'+f
            if os.path.isdir(f):
                subFiles = readDir(f)
                allFiles = subFiles + allFiles #合并当前目录与子目录的所有文件路径
            else:
                allFiles.append(f)
        return allFiles
    else:
        print('Error,not a dir')
    return allFiles

#根据路径筛选出非目标图片的路径
def filterPicture(fileList):
    for fileName in fileList:
        # data = open(fileName, 'rb').read(20)
        fileType = imghdr.what(fileName)
        # print("filename = %s fileType = %s" % (fileName,fileType))

        if fileType != "jpeg" and fileType != "png" and fileType != "bmp":
            print("filename = %s can not parse fileType = %s " % (fileName, fileType))

def main():
    init()
    fileList = readDir(IMAGEPATH)
    filterPicture(fileList)


if __name__ == '__main__':
    main()

Kotlin通过jni间接调用c++

| Comments

本篇重点内容,Kotlin通过JNI直接调用C,C调用C++相关的类。实际上只是JAVA换成Kotlin的写法而已。

一.添加Kotlin类KotlinPerson

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
31
32
33
34
35
36
37
38
class KotlinPerson {

    var mPerson: Long = 0

    init {
        mPerson = createPerson()
    }

    fun setPersonName(name: String) {
        setName(mPerson, name)
    }

    fun personName(): String {
        return name(mPerson)
    }


    fun setPersonAge(age: Int) {
        setAge(mPerson,age)
    }

    fun personAge() : Int {
        return age(mPerson)
    }

    companion object {
        init {
            System.loadLibrary("JNIPerson")
        }
    }

    external fun createPerson(): Long
    external fun destroyPerson(person: Long)
    external fun setName(person: Long, name: String)
    external fun name(person: Long): String
    external fun setAge(person: Long, age: Int)
    external fun age(person: Long): Int
}

二.添加JNI接口及实现

JNIPerson.c内容如下:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
  #include "JNIPerson.h"
  #include "PersonExtension.hpp"
  #include "JNILog.h"
  #include <stdlib.h>
  #include <string.h>
  
  
    /*
    * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
    * Method:    createPerson
    * Signature: ()Ljava/lang/Object;
    */
  JNIEXPORT jlong JNICALL Java_com_ksnowlv_kotlinjni_KotlinPerson_createPerson
      (JNIEnv *env, jobject cls) {
  
  
        void *p = createPerson();
  
        return (jlong)p;
      }
  
    /*
    * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
    * Method:    destroyPerson
    * Signature: (Ljava/lang/Object;)V
    */
    JNIEXPORT void JNICALL Java_com_ksnowlv_kotlinjni_KotlinPerson_destroyPerson
      (JNIEnv *env, jobject cls, jlong o) {
  
          destroyPerson((void*)o);
      }
  
    /*
    * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
    * Method:    setPersonAge
    * Signature: (Ljava/lang/Object;I)V
    */
    JNIEXPORT void JNICALL Java_com_ksnowlv_kotlinjni_KotlinPerson_setAge
      (JNIEnv *env, jobject cls, jlong o, jint value) {
        setPersonAge((void*)o,value);
      }
  
    /*
    * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
    * Method:    personAge
    * Signature: (Ljava/lang/Object;)I
    */
    JNIEXPORT jint JNICALL Java_com_ksnowlv_kotlinjni_KotlinPerson_age
      (JNIEnv *env, jobject cls, jlong o) {
       return personAge((void*)o);
      }
  
  
    JNIEXPORT void JNICALL Java_com_ksnowlv_kotlinjni_KotlinPerson_setName
      (JNIEnv *env, jobject cls, jlong o, jstring string) {
  
        int length1 = (*env)->GetStringLength(env, string);
        const jchar * jcstr = (*env)->GetStringChars(env, string, NULL);
  
  
         jclass   clsstring   =   (*env)->FindClass(env,"java/lang/String");  //String
         jstring   code   =   (*env)->NewStringUTF(env,"UTF-8"); //"UTF-8"
         jmethodID   methodID   =   (*env)->GetMethodID(env,clsstring,   "getBytes",   "(Ljava/lang/String;)[B"); //getBytes();
         jbyteArray   byteArray =   (jbyteArray)(*env)->CallObjectMethod(env,string,methodID,code);
         jsize   length   =   (*env)->GetArrayLength(env,byteArray);
         jbyte*   bytes   =   (*env)->GetByteArrayElements(env,byteArray,JNI_FALSE);
  
  
         if( length > 0){
  
            char* buf =   (char*)malloc(length+1);         //"\0"
            memcpy(buf,bytes,length);
            buf[length]=0;
            setPersonName((void*)o, buf);
            LOGI("set name = %s",buf);
            free(buf);
         }else{
            setPersonName((void*)o, NULL);
         }
  
         (*env)->ReleaseByteArrayElements(env,byteArray,bytes,0);  //释放内存空间
      }
  
    /*
    * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
    * Method:    personName
    * Signature: (Ljava/lang/Object;)Ljava/lang/String;
    */
    JNIEXPORT jstring JNICALL Java_com_ksnowlv_kotlinjni_KotlinPerson_name
      (JNIEnv *env, jobject cls, jlong o) {
  
        LOGI("jni get name");
        const char *name = personName((void*)o);
  
        if ( name != NULL ) {
            LOGI("jni name = %s",name);
            return  (*env)->NewStringUTF(env,name);
        }else {
            return (*env)->NewStringUTF(env,"");
        }
      }
  #include "JNIPerson.h"
#include "PersonExtension.hpp"
#include "JNILog.h"
#include <stdlib.h>
#include <string.h>


  /*
   * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
   * Method:    createPerson
   * Signature: ()Ljava/lang/Object;
   */
JNIEXPORT jlong JNICALL Java_com_ksnowlv_kotlinjni_KotlinPerson_createPerson
    (JNIEnv *env, jobject cls) {


      void *p = createPerson();

      return (jlong)p;
    }

  /*
   * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
   * Method:    destroyPerson
   * Signature: (Ljava/lang/Object;)V
   */
  JNIEXPORT void JNICALL Java_com_ksnowlv_kotlinjni_KotlinPerson_destroyPerson
    (JNIEnv *env, jobject cls, jlong o) {

        destroyPerson((void*)o);
    }

  /*
   * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
   * Method:    setPersonAge
   * Signature: (Ljava/lang/Object;I)V
   */
  JNIEXPORT void JNICALL Java_com_ksnowlv_kotlinjni_KotlinPerson_setAge
    (JNIEnv *env, jobject cls, jlong o, jint value) {
      setPersonAge((void*)o,value);
    }

  /*
   * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
   * Method:    personAge
   * Signature: (Ljava/lang/Object;)I
   */
  JNIEXPORT jint JNICALL Java_com_ksnowlv_kotlinjni_KotlinPerson_age
    (JNIEnv *env, jobject cls, jlong o) {
     return personAge((void*)o);
    }


  JNIEXPORT void JNICALL Java_com_ksnowlv_kotlinjni_KotlinPerson_setName
    (JNIEnv *env, jobject cls, jlong o, jstring string) {

      int length1 = (*env)->GetStringLength(env, string);
      const jchar * jcstr = (*env)->GetStringChars(env, string, NULL);


       jclass   clsstring   =   (*env)->FindClass(env,"java/lang/String");  //String
       jstring   code   =   (*env)->NewStringUTF(env,"UTF-8"); //"UTF-8"
       jmethodID   methodID   =   (*env)->GetMethodID(env,clsstring,   "getBytes",   "(Ljava/lang/String;)[B"); //getBytes();
       jbyteArray   byteArray =   (jbyteArray)(*env)->CallObjectMethod(env,string,methodID,code);
       jsize   length   =   (*env)->GetArrayLength(env,byteArray);
       jbyte*   bytes   =   (*env)->GetByteArrayElements(env,byteArray,JNI_FALSE);


       if( length > 0){

          char* buf =   (char*)malloc(length+1);         //"\0"
          memcpy(buf,bytes,length);
          buf[length]=0;
          setPersonName((void*)o, buf);
          LOGI("set name = %s",buf);
          free(buf);
       }else{
          setPersonName((void*)o, NULL);
       }

       (*env)->ReleaseByteArrayElements(env,byteArray,bytes,0);  //释放内存空间
    }

  /*
   * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
   * Method:    personName
   * Signature: (Ljava/lang/Object;)Ljava/lang/String;
   */
  JNIEXPORT jstring JNICALL Java_com_ksnowlv_kotlinjni_KotlinPerson_name
    (JNIEnv *env, jobject cls, jlong o) {

      LOGI("jni get name");
      const char *name = personName((void*)o);

      if ( name != NULL ) {
          LOGI("jni name = %s",name);
          return  (*env)->NewStringUTF(env,name);
      }else {
          return (*env)->NewStringUTF(env,"");
      }
    }

三.调用

1
2
3
4
5
6
7
var person = KotlinPerson()
person.setPersonAge(10)

Log.i("----Android age = ", "" + person.personAge())
person.setPersonName("ksnowlv(律威)")

Log.i("----Android name = ", person.personName())

四.日志输出

Android通过jni间接调用c++

| Comments

本篇重点内容,C如何调用C++类,思路是JAVA通过JNI直接调用C,C调用C++相关的类。

1.JAVA层接口Person类相关接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class JavaCallJNI {

  static  {
      System.loadLibrary("JNITest");
  }
  
  
  public static native int showValue(int value);
  
  public static native long  createPerson();
  public static native void destroyPerson(long person);
  public static native void setPersonAge(long person,  int age);
  public static native int personAge(long person);
  public static native void setPersonName(long person, String name);
  public static native String  personName(long person);

}

2.C接口及实现

com_ksnowlv_hellojniforjava_JavaCallJNI.h内容如下

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  #include <jni.h>
  /* Header for class com_ksnowlv_hellojniforjava_JavaCallJNI */
  
  #ifndef _Included_com_ksnowlv_hellojniforjava_JavaCallJNI
  #define _Included_com_ksnowlv_hellojniforjava_JavaCallJNI
  #ifdef __cplusplus
  extern "C" {
  #endif
  /*
  * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
  * Method:    showValue
  * Signature: (I)I
  */
  JNIEXPORT jint JNICALL Java_com_ksnowlv_hellojniforjava_JavaCallJNI_showValue
    (JNIEnv *, jclass, jint);
  
  /*
  * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
  * Method:    createPerson
  * Signature: ()J
  */
  JNIEXPORT jlong JNICALL Java_com_ksnowlv_hellojniforjava_JavaCallJNI_createPerson
    (JNIEnv *, jclass);
  
  /*
  * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
  * Method:    destroyPerson
  * Signature: (J)V
  */
  JNIEXPORT void JNICALL Java_com_ksnowlv_hellojniforjava_JavaCallJNI_destroyPerson
    (JNIEnv *, jclass, jlong);
  
  /*
  * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
  * Method:    setPersonAge
  * Signature: (JI)V
  */
  JNIEXPORT void JNICALL Java_com_ksnowlv_hellojniforjava_JavaCallJNI_setPersonAge
    (JNIEnv *, jclass, jlong, jint);
  
  /*
  * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
  * Method:    personAge
  * Signature: (J)I
  */
  JNIEXPORT jint JNICALL Java_com_ksnowlv_hellojniforjava_JavaCallJNI_personAge
    (JNIEnv *, jclass, jlong);
  
  /*
  * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
  * Method:    setPersonName
  * Signature: (JLjava/lang/String;)V
  */
  JNIEXPORT void JNICALL Java_com_ksnowlv_hellojniforjava_JavaCallJNI_setPersonName
    (JNIEnv *, jclass, jlong, jstring);
  
  /*
  * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
  * Method:    personName
  * Signature: (J)Ljava/lang/String;
  */
  JNIEXPORT jstring JNICALL Java_com_ksnowlv_hellojniforjava_JavaCallJNI_personName
    (JNIEnv *, jclass, jlong);
  
  #ifdef __cplusplus
  }
  #endif
  #endif
  

com_ksnowlv_hellojniforjava_JavaCallJNI.c内容如下

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include "com_ksnowlv_hellojniforjava_JavaCallJNI.h"
#include "PersonExtension.hpp"
#include "JNILog.h"
#include <stdlib.h>
#include <string.h>

JNIEXPORT jint JNICALL Java_com_ksnowlv_hellojniforjava_JavaCallJNI_showValue
  (JNIEnv * enc, jclass cls , jint value) {

    LOGI("jni value = %d",value);
  value = value + 1;
  LOGI("jni value +1 = %d",value);
    return value;
  }


/*
 * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
 * Method:    createPerson
 * Signature: ()Ljava/lang/Object;
 */
JNIEXPORT jlong JNICALL Java_com_ksnowlv_hellojniforjava_JavaCallJNI_createPerson
  (JNIEnv *env, jclass cls) {


    void *p = createPerson();

    return (jlong)p;
  }

/*
 * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
 * Method:    destroyPerson
 * Signature: (Ljava/lang/Object;)V
 */
JNIEXPORT void JNICALL Java_com_ksnowlv_hellojniforjava_JavaCallJNI_destroyPerson
  (JNIEnv *env, jclass cls, jlong o) {

      destroyPerson((void*)o);
  }

/*
 * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
 * Method:    setPersonAge
 * Signature: (Ljava/lang/Object;I)V
 */
JNIEXPORT void JNICALL Java_com_ksnowlv_hellojniforjava_JavaCallJNI_setPersonAge
  (JNIEnv *env, jclass cls, jlong o, jint value) {
    setPersonAge((void*)o,value);
  }

/*
 * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
 * Method:    personAge
 * Signature: (Ljava/lang/Object;)I
 */
JNIEXPORT jint JNICALL Java_com_ksnowlv_hellojniforjava_JavaCallJNI_personAge
  (JNIEnv *env, jclass cls, jlong o) {
   return personAge((void*)o);
  }

/*
 * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
 * Method:    setPersonName
 * Signature: (Ljava/lang/Object;Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_ksnowlv_hellojniforjava_JavaCallJNI_setPersonName
  (JNIEnv *env, jclass cls, jlong o, jstring string) {

    int length1 = (*env)->GetStringLength(env, string);
    const jchar * jcstr = (*env)->GetStringChars(env, string, NULL);


     jclass   clsstring   =   (*env)->FindClass(env,"java/lang/String");  //String
     jstring   code   =   (*env)->NewStringUTF(env,"UTF-8"); //"UTF-8"
     jmethodID   methodID   =   (*env)->GetMethodID(env,clsstring,   "getBytes",   "(Ljava/lang/String;)[B"); //getBytes();
     jbyteArray   byteArray =   (jbyteArray)(*env)->CallObjectMethod(env,string,methodID,code);
     jsize   length   =   (*env)->GetArrayLength(env,byteArray);
     jbyte*   bytes   =   (*env)->GetByteArrayElements(env,byteArray,JNI_FALSE);


     if( length > 0){

        char* buf =   (char*)malloc(length+1);         //"\0"
        memcpy(buf,bytes,length);
        buf[length]=0;
        setPersonName((void*)o, buf);
        LOGI("set name = %s",buf);
        free(buf);
     }else{
        setPersonName((void*)o, NULL);
     }

     (*env)->ReleaseByteArrayElements(env,byteArray,bytes,0);  //释放内存空间
  }

/*
 * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
 * Method:    personName
 * Signature: (Ljava/lang/Object;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_ksnowlv_hellojniforjava_JavaCallJNI_personName
  (JNIEnv *env, jclass cls, jlong o) {

    LOGI("jni get name");
    const char *name = personName((void*)o);

    if ( name != NULL ) {
        LOGI("jni name = %s",name);
        return  (*env)->NewStringUTF(env,name);
    }else {
        return (*env)->NewStringUTF(env,"");
    }
  }

3.JAVA调用

1
2
3
4
5
6
7
8
9
10
11
int value =  JavaCallJNI.showValue(1);
Log.i("------Android ","" + value);

long p =  JavaCallJNI.createPerson();
JavaCallJNI.setPersonAge(p,10);
int age = JavaCallJNI.personAge(p);
Log.i("------Android ","" + age);
JavaCallJNI.setPersonName(p,"ksnowlv(律威)");
String name = JavaCallJNI.personName(p);
Log.i("------Android ",name);
JavaCallJNI.destroyPerson(p);

4.日志输出

28410-28410/com.ksnowlv.hellojniforjava I/------JNITest: jni value = 1
2019-04-24 16:42:40.759 28410-28410/com.ksnowlv.hellojniforjava I/------JNITest: jni value +1 = 2
2019-04-24 16:42:40.759 28410-28410/com.ksnowlv.hellojniforjava I/------Android: 2
2019-04-24 16:42:40.759 28410-28410/com.ksnowlv.hellojniforjava I/------Android: 10
2019-04-24 16:42:40.759 28410-28410/com.ksnowlv.hellojniforjava I/------JNITest: set name = ksnowlv(律威)
2019-04-24 16:42:40.759 28410-28410/com.ksnowlv.hellojniforjava I/------JNITest: jni get name
2019-04-24 16:42:40.759 28410-28410/com.ksnowlv.hellojniforjava I/------JNITest: jni name = ksnowlv(律威)
2019-04-24 16:42:40.759 28410-28410/com.ksnowlv.hellojniforjava I/------Android: ksnowlv(律威)

Android通过jni调用c++

| Comments

本篇重点内容在于如何把C++的类通过JNI转换为JAVA的类

1.创建JAVA类:JavaPerson

public class JavaPerson {


private long mNativePerson;

public JavaPerson()
{
    mNativePerson = init();
}

public int getAge()
{
    return this.native_getAge(mNativePerson);
}

public void setAge(int age)
{
    native_setAge(mNativePerson, age);
}

public String getName() {
    return native_getName(mNativePerson);
}

public void setName(String name) {
    native_setName(mNativePerson, name);
}


@Override
protected void finalize() throws Throwable {

    if (mNativePerson != 0) {
        finalizer(mNativePerson);
    }

    super.finalize();
}

    static {
        System.loadLibrary("jniPerson");
    }

    private native long  init();
    private native void finalizer(long aPerson);
    private native int native_getAge(long aPerson);
    private native void native_setAge(long aPerson, int age);
    private native String native_getName(long aPerson);
    private native void native_setName(long aPerson, String name);
}

2.通过Terminal生成c++头文件:com_ksnowlv_jnicallc_JavaPerson.h

#ifndef _Included_com_ksnowlv_jnicallc_JavaPerson
#define _Included_com_ksnowlv_jnicallc_JavaPerson
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_ksnowlv_jnicallc_JavaPerson
 * Method:    init
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL Java_com_ksnowlv_jnicallc_JavaPerson_init
  (JNIEnv *, jobject);

/*
 * Class:     com_ksnowlv_jnicallc_JavaPerson
 * Method:    finalizer
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_com_ksnowlv_jnicallc_JavaPerson_finalizer
  (JNIEnv *, jobject, jlong);

/*
 * Class:     com_ksnowlv_jnicallc_JavaPerson
 * Method:    native_getAge
 * Signature: (J)I
 */
JNIEXPORT jint JNICALL Java_com_ksnowlv_jnicallc_JavaPerson_native_1getAge
  (JNIEnv *, jobject, jlong);

/*
 * Class:     com_ksnowlv_jnicallc_JavaPerson
 * Method:    native_setAge
 * Signature: (JI)V
 */
JNIEXPORT void JNICALL Java_com_ksnowlv_jnicallc_JavaPerson_native_1setAge
  (JNIEnv *, jobject, jlong, jint);

/*
 * Class:     com_ksnowlv_jnicallc_JavaPerson
 * Method:    native_getName
 * Signature: (J)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_ksnowlv_jnicallc_JavaPerson_native_1getName
  (JNIEnv *, jobject, jlong);

/*
 * Class:     com_ksnowlv_jnicallc_JavaPerson
 * Method:    native_setName
 * Signature: (JLjava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_ksnowlv_jnicallc_JavaPerson_native_1setName
  (JNIEnv *, jobject, jlong, jstring);

#ifdef __cplusplus
}
#endif
#endif

3.添加c++实现文件:com_ksnowlv_jnicallc_JavaPerson.cpp

//
// Created by ksnowlv on 2019-04-18.
//

#include"com_ksnowlv_jnicallc_JavaPerson.h"
#include "Person.hpp"
#include "JNILog.h"
#include <string.h>

extern "C"
{

/*
 * Class:     com_ksnowlv_jnicallc_JavaPerson
 * Method:    init
 * Signature: ()I
 */
JNIEXPORT jlong JNICALL Java_com_ksnowlv_jnicallc_JavaPerson_init
  (JNIEnv *, jobject) {

      LOGE("JNI Java_com_ksnowlv_jnicallc_JavaPerson_init");
      Person *person = new Person();
      return (jlong)person;

  }

/*
 * Class:     com_ksnowlv_jnicallc_JavaPerson
 * Method:    finalizer
 * Signature: (J)V
 */
JNIEXPORT void JNICALL Java_com_ksnowlv_jnicallc_JavaPerson_finalizer
  (JNIEnv *, jobject cls, jlong thisObject) {

    LOGE("JNI Java_com_ksnowlv_jnicallc_JavaPerson_finalizer");

    Person *person = (Person *)thisObject;

    if (NULL != person) {
        delete person;
        person = NULL;
    }

  }

/*
 * Class:     com_ksnowlv_jnicallc_JavaPerson
 * Method:    native_getAge
 * Signature: (J)I
 */
JNIEXPORT jint JNICALL Java_com_ksnowlv_jnicallc_JavaPerson_native_1getAge
  (JNIEnv *evn, jobject cls, jlong thisObject ) {

    Person *person = (Person *)thisObject;

    LOGE("JNI Java_com_ksnowlv_jnicallc_JavaPerson_native_1getAge= %d", person->age());

    if (NULL != person) {

        return person->age();
    }

    return -1;
  }

/*
 * Class:     com_ksnowlv_jnicallc_JavaPerson
 * Method:    native_setAge
 * Signature: (JI)V
 */
JNIEXPORT void JNICALL Java_com_ksnowlv_jnicallc_JavaPerson_native_1setAge
  (JNIEnv *env, jobject cls, jlong thisObject, jint age ) {

      LOGE("JNI Java_com_ksnowlv_jnicallc_JavaPerson_native_1setAge = %d", age);

      Person *person = (Person *)thisObject;

      if ( NULL != person ) {
        person->setAge(age);
      }
  }

/*
 * Class:     com_ksnowlv_jnicallc_JavaPerson
 * Method:    native_getName
 * Signature: (J)I
 */
JNIEXPORT jstring JNICALL Java_com_ksnowlv_jnicallc_JavaPerson_native_1getName
  (JNIEnv *env, jobject cls, jlong thisObject) {
      LOGE("JNI Java_com_ksnowlv_jnicallc_JavaPerson_native_1getName");

      Person *person = (Person *)thisObject;

      if ( NULL != person ) {
          const char *name = person->name();
          if ( name != NULL ) {
               // LOGI("JNI name = %s",name);
                return  env->NewStringUTF(name);
           }
       }

    return env->NewStringUTF("");
  }

/*
 * Class:     com_ksnowlv_jnicallc_JavaPerson
 * Method:    native_setName
 * Signature: (JLjava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_com_ksnowlv_jnicallc_JavaPerson_native_1setName
  (JNIEnv *env, jobject cls, jlong thisObject, jstring string) {

    LOGE("JNI Java_com_ksnowlv_jnicallc_JavaPerson_native_1setName");

     jclass   clsstring   =   env->FindClass("java/lang/String");  //String
     jstring   code   =   env->NewStringUTF("UTF8"); //"UTF8"
     jmethodID   methodID   =   env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B"); //getBytes(String);
     jbyteArray   byteArray =   (jbyteArray)env->CallObjectMethod(string,methodID,code); // String .getByte("UTF8");
     jsize   length   =   env->GetArrayLength(byteArray);
     jbyte*   bytes   =   env->GetByteArrayElements(byteArray,JNI_FALSE);

    Person *person = (Person *)thisObject;

    if ( NULL != person ) {
       if( length > 0){
            char* buf =   new char[length+1];
            memset(buf,0,length+1);
            memcpy(buf,bytes,length);
            person->setName(buf);
            LOGE("JNI set name = %s",buf);
            delete []buf;
         }else{
            person->setName(NULL);
         }
    }



     env->ReleaseByteArrayElements(byteArray,bytes,0);  //释放内存空间
  }

}

static  JNINativeMethod methods[] = {

        {"init", "()J", (void *)Java_com_ksnowlv_jnicallc_JavaPerson_init},
        {"finalizer", "(J)V", (void *)Java_com_ksnowlv_jnicallc_JavaPerson_finalizer},
        {"native_getAge", "(J)I", (void *)Java_com_ksnowlv_jnicallc_JavaPerson_native_1getAge},
        {"native_setAge", "(JI)V", (void *)Java_com_ksnowlv_jnicallc_JavaPerson_native_1setAge},
        {"native_getName", "(J)Ljava/lang/String;", (void *)Java_com_ksnowlv_jnicallc_JavaPerson_native_1getName},
        {"native_setName", "(JLjava/lang/String;)V", (void *)Java_com_ksnowlv_jnicallc_JavaPerson_native_1setName},
};





static const char * classPathName = "com/ksnowlv/jnicallc/JavaPerson";
/*
 * Register several native methods for one class.
 */
static int registerNativeMethods(JNIEnv* env, const char* className,
                                 JNINativeMethod* gMethods, int numMethods)
{
    jclass clazz;
    clazz = env->FindClass(className);
    if (clazz == NULL) {
        LOGE("JavaPerson Native registration unable to find class '%s'", className);
        return JNI_FALSE;
    }
    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
        LOGE("JavaPerson RegisterNatives failed for '%s'", className);
        return JNI_FALSE;
    }

    LOGE("JavaPerson registerNativeMethods OK");
    return JNI_TRUE;
}
/*
 * Register native methods for all classes we know about.
 *
 * returns JNI_TRUE on success.
 */
static int registerNatives(JNIEnv* env)
{
    if (!registerNativeMethods(env, classPathName,
                               methods, sizeof(methods) / sizeof(methods[0]))) {
        LOGE("JavaPerson class registerNatives FAIL");
        return JNI_FALSE;
    }

    LOGE("JavaPerson registerNatives OK");
    return JNI_TRUE;
}
// ----------------------------------------------------------------------------
/*
 * This is called by the VM when the shared library is first loaded.
 */

typedef union {
    JNIEnv* env;
    void* venv;
} UnionJNIEnvToVoid;

jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    UnionJNIEnvToVoid uenv;
    uenv.venv = NULL;
    jint result = -1;
    JNIEnv* env = NULL;

    LOGE("JNI_OnLoad");
    if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
        LOGE("ERROR: GetEnv failed");
        goto bail;
    }
    env = uenv.env;
    if (registerNatives(env) != JNI_TRUE) {
        LOGE("ERROR: registerNatives failed");
        goto bail;
    }

    result = JNI_VERSION_1_4;

    LOGE("JNI_OnLoad OK");
    bail:
    return result;
}

4.在Android中的调用

   JavaPerson person = new JavaPerson();
    person.setAge(10);
    Log.i("------JNICallC++: Android person age =  ","" + person.getAge());
    person.setName("ksnowlv(律威)");
    Log.i("------JNICallC++: Android person name =  ","" + person.getName());   

5.输出

2019-04-19 17:02:27.114 30422-30422/? E/------JNICallC++: JNI_OnLoad
2019-04-19 17:02:27.115 30422-30422/? E/------JNICallC++: JavaPerson registerNativeMethods OK
2019-04-19 17:02:27.115 30422-30422/? E/------JNICallC++: JavaPerson registerNatives OK
2019-04-19 17:02:27.115 30422-30422/? E/------JNICallC++: JNI_OnLoad OK
2019-04-19 17:02:27.115 30422-30422/? E/------JNICallC++: JNI Java_com_ksnowlv_jnicallc_JavaPerson_init
2019-04-19 17:02:27.115 30422-30422/? E/------JNICallC++: JNI Java_com_ksnowlv_jnicallc_JavaPerson_native_1setAge = 10
2019-04-19 17:02:27.115 30422-30422/? E/------JNICallC++: JNI Java_com_ksnowlv_jnicallc_JavaPerson_native_1getAge= 10
2019-04-19 17:02:27.115 30422-30422/? I/------JNICallC++: Android person age =: 10
2019-04-19 17:02:27.115 30422-30422/? E/------JNICallC++: JNI Java_com_ksnowlv_jnicallc_JavaPerson_native_1setName
2019-04-19 17:02:27.116 30422-30422/? E/------JNICallC++: JNI set name = ksnowlv(律威)
2019-04-19 17:02:27.116 30422-30422/? E/------JNICallC++: JNI Java_com_ksnowlv_jnicallc_JavaPerson_native_1getName
2019-04-19 17:02:27.116 30422-30422/? I/------JNICallC++: Android person name =: ksnowlv(律威)

6.说明

  • C++Person类同上一工程 。
  • 注意JNI调用C++和C的区别。
    • JNI_OnLoad相关:像JNINativeMethod methods注意函数映射参数,classPathName类路径等
    • env调用方式
    • C++对象回收内存

Android-jni-demo

| Comments

1.创建app/src/main/jniLibs目录

2.把so库拷贝到jniLibs目录。

3.JavaCallJNI内容如下

···objective-c

public class JavaCallJNI {

static  {
    System.loadLibrary("JNITest");
}


public static native int showValue(int value);

}

···

4.com_ksnowlv_hellojniforjava_JavaCallJNI.h内容如下:

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
/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class com_ksnowlv_hellojniforjava_JavaCallJNI */

#ifndef _Included_com_ksnowlv_hellojniforjava_JavaCallJNI

#define _Included_com_ksnowlv_hellojniforjava_JavaCallJNI

#ifdef __cplusplus

extern "C" {

#endif
/*
 * Class:     com_ksnowlv_hellojniforjava_JavaCallJNI
 * Method:    showValue
 * Signature: (I)I
 */

JNIEXPORT jint JNICALL Java_com_ksnowlv_hellojniforjava_JavaCallJNI_showValue
  (JNIEnv *, jclass, jint);

  #ifdef __cplusplus
}

#endif

#endif

5.com_ksnowlv_hellojniforjava_JavaCallJNI.c内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include "com_ksnowlv_hellojniforjava_JavaCallJNI.h"
#include "PersonExtension.hpp"
#include "JNILog.h"


JNIEXPORT jint JNICALL Java_com_ksnowlv_hellojniforjava_JavaCallJNI_showValue
  (JNIEnv * enc, jclass cls , jint value) {

    LOGI("jni value = %d",value);
  value = value + 1;
  LOGI("jni value +1 = %d",value);
    return value;
  }

6。Android中调用如下:

1
2
  int value =  JavaCallJNI.showValue(1);
  Log.e("#### value ","" + value);

Android

”mac下配置jni开发环境(二)“

| Comments

创建android基础工程

1.JNI java文件创建

1
2
3
4
5
6
7
8
public class JavaCallJNI {

    static  {
        System.loadLibrary("JniTest");
    }

    public static native int showValue(int value);
}

image

2.在app/scr/main/目录下,创建目录jni

3.在jni目录下,创建Android.mk文件

文件内容如下:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)


LOCAL_MODULE := jniTest
LOCAL_SRC_FILES := com_ksnowlv_hellojniforjava_JavaCallJNI.c

include $(BUILD_SHARED_LIBRARY)

其中

  • LOCAL_MODULE := JniTest

      这里JniTest,是将要生成的`.so`库的名字,会自动加上 lib前缀,
      最终生成库文件:libJniTest.so
      如果要引用该库:System.loadLibrary("JniTest")
    
  • LOCAL_SRC_FILES := com_ksnowlv_hellojniforjava_JavaCallJNI

      JNI头文件com_ksnowlv_hellojniforjava_JavaCallJNI.h对应的.c文件
      命名方式:包名+类名+.c
    

terminal中生成com_ksnowlv_hellojniforjava_JavaCallJNI.h头文件

ksnowlvdeMacBook-Pro:java ksnowlv$ javac com/ksnowlv/   hellojniforjava/JavaCallJNI.java 
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
ksnowlvdeMacBook-Pro:java ksnowlv$ javah -d ../jni  com.ksnowlv.hellojniforjava.JavaCallJNI
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
ksnowlvdeMacBook-Pro:java ksnowlv$ cd ..

image

实现文件中内容如下

#include "com_ksnowlv_hellojniforjava_JavaCallJNI.h"

JNIEXPORT jint JNICALL  Java_com_ksnowlv_hellojniforjava_JavaCallJNI_showValue(JNIEnv * enc, jclass cls , jint value) {
    value = value + 1;
    return value;
}

4.在jni目录下,创建Application.mk文件

内容如下:

APP_ABI := all  

会生成所有主流 ABI 类型的 .so 库

5.更新在当前模块下build.gradle文件

  • defaultConfig下增加ndk配置

      ndk {
          moduleName "JniTest" //System.loadLibrary("JniTest");
      }
    
  • 在buildTypes上面添加jni.srcDirs的配置

      sourceSets {
         main {//建议这里直接使用'libs'目录,
         //因为当使用其他包有.so文件时,一般习惯也是直接拷贝进入libs目录
          jni.srcDirs = ['libs']
        }
      }
    

image

5.在终端进入jni路径:app/src/main/jni,输入ndk-build即生成各种版本的so

ksnowlvdeMacBook-Pro:java ksnowlv$ javac com/ksnowlv/   hellojniforjava/JavaCallJNI.java 
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
ksnowlvdeMacBook-Pro:java ksnowlv$ javah -d ../jni  com.ksnowlv.hellojniforjava.JavaCallJNI
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
ksnowlvdeMacBook-Pro:java ksnowlv$ cd ..
ksnowlvdeMacBook-Pro:main ksnowlv$ cd jni
ksnowlvdeMacBook-Pro:jni ksnowlv$ ndk-build

image

”mac下android配置jni开发环境(一)“

| Comments

mac机器上,在进行jni开发之前,android studio 3.3.2,需要配置java环境与ndk环境。

一.配置java环境参数

1.通过which java查看Mac下jdk安装目录

ksnowlvdeMacBook-Pro:~ ksnowlv$ which java
/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java

image

2.在.bash_profile文件中配置java环境

JAVA_HOME=/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
PATH=$JAVA_HOME/bin:$PATH:.
CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.

export JAVA_HOME
export PATH
export CLASSPATH

3.保存.bash_profile,并使之生效。

ksnowlvdeMacBook-Pro:~ ksnowlv$ source .bash_profile

ksnowlvdeMacBook-Pro:~ ksnowlv$ echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home

ksnowlvdeMacBook-Pro:~ ksnowlv$ java -version
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
java version "1.6.0_65"
Java(TM) SE Runtime Environment (build 1.6.0_65-b14-468)
Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-468, mixed mode)

二.配置ndk。

1.在.bash_profile文件中配置ndk路径

export ANDROID_NDK_ROOT=/Users/ksnowlv/Library/Android/sdk/ndk-bundle 
export ANDROID_SDK_ROOT=/Users/ksnowlv/Library/Android/sdk

export PATH=$PATH:$ANDROID_SDK_ROOT  
export PATH=$PATH:$ANDROID_NDK_ROOT 

ndk路径,sdk路径一定要与实际目录一致,参考下图
image

2.保存.bash_profile,并使之生效。

ksnowlvdeMacBook-Pro:~ ksnowlv$ source .bash_profile
ksnowlvdeMacBook-Pro:~ ksnowlv$ echo $ANDROID_NDK_ROOT
/Users/ksnowlv/Library/Android/sdk/ndk-bundle
ksnowlvdeMacBook-Pro:~ ksnowlv$ echo $ANDROID_SDK_ROOT
/Users/ksnowlv/Library/Android/sdk
ksnowlvdeMacBook-Pro:~ ksnowlv$ 

三.其它

1.为什么不使用jdk-12.jdk?而使用了旧版jdk?

javah命令在旧版有效。新版可使用javac -h

300指数量化基金

| Comments

基金代码 简称 2016超越沪深300指数% 2017超越300指数% 2018超越300指数% 3年平均收益率% 基金规模 管理托管费%
163497 兴全沪深300指数增强 11.98 10.05 8.36 10.13 20.25亿元|0.95
100038 富国沪深300指数增强 6.27 5.3 8.37 6.65 58.83亿元|1.18
00012 华安沪深300增强A 8.33 8.95 3.95 7.08 1.75亿元|1.15
519116 浦银沪深300增强 6.6 4.36 5.79 5.59 1.11|1.15
110030 易方达沪深量化300增强 9.47 8.06 2.15 6.56 9.86|0.95
000887 华泰柏瑞量化优选 13.93 2.59 3.03 6.52 40.77 1.25

计划新增兴全沪深300指数增强,易方达沪深量化300增强长期定投

Swift Call C++(二)

| Comments

如何在swift调整c++代码呢?

swift通过工程的桥接文件,调用oc的代码,间接调用c++代码!!!

1.创建C++ Person类文件:Person.hppPerson.cpp

Person.hpp内容如下:

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
31
//
//  Person.hpp
//  SwiftCallC
//
//  Created by ksnowlv on 2019/3/28.
//  Copyright © 2019 ksnowlv. All rights reserved.
//

#ifndef Person_hpp
#define Person_hpp

#include <stdio.h>

class Person {
public:
    Person();
    ~Person();

    void setName(const char* pName);
    const char* name();

    void setAge(const int age);
    const int age() const;

private:
    char *m_pName;
    int m_age;
};


#endif /* Person_hpp */

Person.cpp内容如下

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
//
//  Person.cpp
//  SwiftCallC
//
//  Created by ksnowlv on 2019/3/28.
//  Copyright © 2019 ksnowlv. All rights reserved.
//

#include "Person.hpp"
#include <string.h>


Person::Person() {
    m_pName = nullptr;
    m_age = 0;
}

Person::~Person() {

    if (m_pName) {
        delete [] m_pName;
        m_pName = nullptr;
    }
}

void Person::setAge(const int age) {
    m_age = age;
}

const int Person::age()const {
    return m_age;
}

void Person::setName(const char *pName) {
    if (m_pName) {
        delete [] m_pName;
        m_pName = nullptr;
    }

    if (pName) {
        const size_t len = strlen(pName) + 1;
        m_pName = new char[len];
        memset(m_pName, 0, len);
        strcpy(m_pName, pName);
    }
}

const char* Person::name() {
    return m_pName;
}

2.创建oc类文件:PersonExt.hPersonExt.mm

PersonExt.h内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//
//  PersonExt.h
//  SwiftCallC
//
//  Created by ksnowlv on 2019/4/1.
//  Copyright © 2019 ksnowlv. All rights reserved.
//

#import <Foundation/Foundation.h>


NS_ASSUME_NONNULL_BEGIN

@interface PersonExt : NSObject


@property(nonatomic, strong) NSString *name;
@property(nonatomic, assign) NSInteger age;


@end

NS_ASSUME_NONNULL_END

PersonExt.mm内容如下

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//
//  PersonExt.m
//  SwiftCallC
//
//  Created by ksnowlv on 2019/4/1.
//  Copyright © 2019 ksnowlv. All rights reserved.
//

#import "PersonExt.h"
#include "Person.hpp"

@interface PersonExt () {
    Person *_person;
}


@end

@implementation PersonExt

- (id)init {
    self = [super init];

    if (self) {
        _person = new Person();
    }

    return self;
}

- (void)dealloc {

    if (_person) {
        delete _person;
        _person = nil;
    }
}

- (void)setName:(NSString *)name {
    if (_person) {
        _person->setName([name UTF8String]);
    }
}

- (NSString *)name {
    if (_person) {
        const char *name = _person->name();

        if (name) {
            return  [NSString stringWithUTF8String:name];
        }
    }

    return nil;
}

- (void)setAge:(NSInteger)age {

    if (_person) {
        _person->setAge((const int)age);
    }
}

- (NSInteger)age {
    if (_person) {
        return  _person->age();
    }

    return 0;
}

@end

3.在桥接文件中,加入PersonExt.h引用:#include "PersonExt.h"

4.swift中调用

1
2
3
4
5
6
7
8
9
    let personExt = PersonExt()
    var age = personExt.age
    print("age =",age)
    personExt.age = 20
    age = personExt.age
    print("age =",age)

    personExt.name = "ksnowlv"
    print("name = ",personExt.name)

结果显而易见:

1
2
3
age = 0
age = 20
name =  ksnowlv
Included file 'custom/after_footer.html' not found in _includes directory