1. 头文件
原因是在eclipse编辑环境中没有找到对应的include中的文件。解决方法是将包含该文件的include目录作为新的linked folder加入工程中。具体方法如下:
1. 右击工程->New->Folder
2. 对话框中点击Advanced
3. 选择Link to alternate location (Linked Folder),选择需要的include目录,例如:/android-ndk-r7b/platforms/android-8/arch-arm/usr/include
4. Finish后刷新工程,问题解决。
1.1) #include <sys/stat.h> 调用linux的stat.h头文件,stat函数可以返回一个结构,里面包括文件的全部属性。
lstat函数类似于stat.但是当命名的文件是一个符号链接时,lstat返回该符号链接的有关信息,而不是由该符号链接引用文件的信息。第二个参数buf是指针,它指向一个我们必须提供的结构,这些函数填写由buf指向的结构。该结构的实际定义可能随实现有所不同.
2.jni中输出打印到Logcat
2.1)导入log头文件 :#include<android/log.h>
路径:/build/platforms/android-8/arch-arm/usr/include/android/log.h
2.2)修改Android.mk
如生成的库文件是“.so文件”,在Android.mk中加上:
LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog
如生成的库文件是“.a文件”,在Android.mk中加上:
LOCAL_LDLIBS:=-llog
注意:Android.mk里有一行 include $(CLEAR_VARS)
必须把LOCAL_LDLIBS :=-llog放在它后面才有用,否则相当于没写。
2.3)定义LOG 函数
先定义一个全局变量,再定义一些输出的LOG函数:
2.4)调用:LOGD("########## i = %d", i);
3. 互斥锁
4.使用C++编写JNI接口
转自:使用C 实现JNI接口需要注意的事项
Android NDK带的jni例子都是使用C定义JNI接口,但是在项目中,因为Native代码是用C++编写的,所以我就使用C++定义JNI接口。没有想到,问题来了,现将问题总结如下:
4.1) JNIEnv *env参数的使用
所有JNI接口的第一个参数是JNIEnv *env, 在C中,使用方法是:(*env)->NewStringUTF(env, "Hello from JNI!");
但在C++中,其调用方法是:env->NewStringUTF("Hello from JNI!");
为什么有这种区别呢,看看jni.h中关于JNIEnv的定义就可以知道了:
4.2)接口找不到,extern "C"
在Java中调用JNI接口时,出现异常,察看日志,发现有如下错误:
WARN/dalvikvm(422): No implementation found for native Lcom/whty/wcity/HelixPlayer;.setDllPath (Ljava/lang/String;)V
检查了几遍代码,Cpp中确实定义了这个接口,而且仔细对照了Java的包名、类名,确实没有错误,那为什么会出现这种问题呢。后来突然想到,JNI接口都是以C的方式定义的,现在使用C++实现,函数定义前是否需要加上extern "C"呢?为此定义了一个头文件,在CPP文件中include该头文件,头文件加上如下代码片断:
Unresolved inclusion错误:#include <jni.h> #include "Symbol.h" #include "yoyon_types.h" #include <android/log.h> #include <stdarg.h> //主要目的为让函数能够接收可变参数。 #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <fcntl.h> #include <stdio.h> #include <sys/stat.h> //stat函数可以返回一个结构,里面包括文件的全部属性。 #include <string.h>
原因是在eclipse编辑环境中没有找到对应的include中的文件。解决方法是将包含该文件的include目录作为新的linked folder加入工程中。具体方法如下:
1. 右击工程->New->Folder
2. 对话框中点击Advanced
3. 选择Link to alternate location (Linked Folder),选择需要的include目录,例如:/android-ndk-r7b/platforms/android-8/arch-arm/usr/include
4. Finish后刷新工程,问题解决。
1.1) #include <sys/stat.h> 调用linux的stat.h头文件,stat函数可以返回一个结构,里面包括文件的全部属性。
#i nclude<sys/stat.h>
int stat(const char *restrict pathname,struct stat *restrict buf);
int fstat(int fields,struct stat *buf);
int lstat(const char *restrict pathname,struct stat *restrict buf);
返回值:若成功则返回0,失败则返回-1
一旦给出pathname,stat函数就返回与此命名文件有关的信息结构,fstat函数获取已在描述符fields上打开文件的有关信息。lstat函数类似于stat.但是当命名的文件是一个符号链接时,lstat返回该符号链接的有关信息,而不是由该符号链接引用文件的信息。第二个参数buf是指针,它指向一个我们必须提供的结构,这些函数填写由buf指向的结构。该结构的实际定义可能随实现有所不同.
struct stat{
mode_t st_mode; //文件类型和权限信息
ino_t st_ino; //i结点标识
dev_t st_dev; //device number (file system)
dev_t st_rdev; //device number for special files
nlink_t st_nlink; //符号链接数
uid_t st_uid; //用户ID
gid_t st_gid; //组ID
off_t st_size; //size in bytes,for regular files
time_t st_st_atime; //最后一次访问的时间
time_t st_mtime; //文件内容最后一次被更改的时间
time_t st_ctime; //文件结构最后一次被更改的时间
blksize_t st_blksize; //best I/O block size
blkcnt_t st_blocks; //number of disk blocks allocated
};
2.jni中输出打印到Logcat
2.1)导入log头文件 :#include<android/log.h>
路径:/build/platforms/android-8/arch-arm/usr/include/android/log.h
2.2)修改Android.mk
如生成的库文件是“.so文件”,在Android.mk中加上:
LOCAL_LDLIBS:=-L$(SYSROOT)/usr/lib -llog
如生成的库文件是“.a文件”,在Android.mk中加上:
LOCAL_LDLIBS:=-llog
注意:Android.mk里有一行 include $(CLEAR_VARS)
必须把LOCAL_LDLIBS :=-llog放在它后面才有用,否则相当于没写。
2.3)定义LOG 函数
先定义一个全局变量,再定义一些输出的LOG函数:
上述代码中定义的函数,分别对应于Android 的Java代码中的 Log.d(), Log.i(), Log.w(),Log.e(), Log.f()等方法.#define TAG "myDemo-jni" // 这个是自定义的LOG的标识 #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型 #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型 #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型
2.4)调用:LOGD("########## i = %d", i);
3. 互斥锁
static pthread_mutex_t hMutex=PTHREAD_MUTEX_INITIALIZER;
#define THREAD_LOCK() do{\
pthread_mutex_lock(&hMutex);\
}while(0)
#define THREAD_UNLOCK() do{\
pthread_mutex_unlock(&hMutex);\
}while(0)
有两种方法创建互斥锁,静态方式和动态方式。POSIX定义宏PTHREAD_MUTEX_INITIALIZER来静态初始化互斥锁: pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; LinuxThreads实现pthread_mutex_t是一个结构,PTHREAD_MUTEX_INITIALIZER则是一个结构常量。
4.使用C++编写JNI接口
转自:使用C 实现JNI接口需要注意的事项
Android NDK带的jni例子都是使用C定义JNI接口,但是在项目中,因为Native代码是用C++编写的,所以我就使用C++定义JNI接口。没有想到,问题来了,现将问题总结如下:
4.1) JNIEnv *env参数的使用
所有JNI接口的第一个参数是JNIEnv *env, 在C中,使用方法是:(*env)->NewStringUTF(env, "Hello from JNI!");
但在C++中,其调用方法是:env->NewStringUTF("Hello from JNI!");
为什么有这种区别呢,看看jni.h中关于JNIEnv的定义就可以知道了:
#if defined(__cplusplus)
typedef _JNIEnv JNIEnv;
#else
typedef const struct JNINativeInterface* JNIEnv;
#endif
可以看到,对于C和C++,定义有所不同,主要原因是C不支持类,所以采用了一种变通的方法。
4.2)接口找不到,extern "C"
在Java中调用JNI接口时,出现异常,察看日志,发现有如下错误:
WARN/dalvikvm(422): No implementation found for native Lcom/whty/wcity/HelixPlayer;.setDllPath (Ljava/lang/String;)V
检查了几遍代码,Cpp中确实定义了这个接口,而且仔细对照了Java的包名、类名,确实没有错误,那为什么会出现这种问题呢。后来突然想到,JNI接口都是以C的方式定义的,现在使用C++实现,函数定义前是否需要加上extern "C"呢?为此定义了一个头文件,在CPP文件中include该头文件,头文件加上如下代码片断:
/*Symbol.h*/
#ifndef _SYMBOL_H_
#define _SYMBOL_H_
#ifdef __cplusplus
extern "C" {
#endif
.....
#ifdef __cplusplus
}
#endif
#endif
再次尝试,调用成功!