android_c++ 高级编程NDK学习笔记四

Bionicc++进行原生应用开发所提供的posix标准c

回顾标准库

Java 平台的标准库是java class library(JCL)

C语言的标准库为libc 

2 gnu c(glibc)  embedded linux c(uclibc) bionic

Bionic提供以下功能:

内存管理

文件输入输出

字符串操作

数学

日期与时间

进程控制

信号处理

网络套接字

多线程

用户和组

系统配置

命名服务切换

 

AndroidNDK提供了缺失功能的完整列表,可以从头文件中获得这些信息

ANDROID_NDK_HOME/platforms/android-<api-level>/arch-<architecture>/usr/include

 

内存管理

三种内存分配方式

静态分配静态或全局变量

自动分配函数参数和局部变量

动态分配内存的大小和范围的分配取决于运行时因素

 

C语言的动态内存管理---------------------------------------------------------------

  动态分配内存

      Void* malloc(size_t size); //是以字节为单位来分配内存的

  释放动态内存:

      Void* free(void* memory);//通过之前指向动态内存的指针来释放内存

  改变动态内存分配

      Void * fealloc(void* memory,size_t size);//重新分配内存

 

 

 

C++ 的动态内存管理 -----------------------------------------------------------------

  动态分配内存:

     示例代码如下:

      //单个元素的动态内存分配

      Int* myInt=new int;

      If(NULL==myInt){

        //不能分配足够的内存

       }else{

        //使用分配的内存

        *myInt=0;

       }

      //多个元素的动态内存分配

      Int* myIntArray=new int[16];

     Int* myIntArray=new int;

      If(NULL==myInt){

        //不能分配足够的内存

       }else{

        //使用分配的内存

          myIntArray[8]=8;

       }

 

   释放动态内存:

     //释放单个元素的动态内存

     Delete myInt;

     myInt=0;

     //释放多个元素的动态内存

     Delete[] myIntArray;

     myIntArray=0;

   

改变动态内存

   使用适当的标准模板库(standard template library STL)

 

 

4标准I/O

 可以通过c库提供的satndard file I/o(stdio)函数与文件系统进行交互

 

 C 库提供了两种文件i/o:

  低级I/O: 原始的i/o函数

  流I/o: 可缓冲的I/O函数适合处理数据流 

 

 标准流  #include <stdio.h>

 Stdin: 标准输入

 Stdout: 标准输出 

 Stderr: 标准错误

 

 

打开流----------------------------------------------------------------------------

 FILE* fopen(const char* filename,//文件名

            const char* opentype);//控制文件打开方式

  R 只读

  W 只写

  A  以符加方式打开文件,不存在则新建

  R+ 在读写模式下打开文件

  W+ 在读写模式下打开文件载断后文件长度为0

  A+ 打开文件进行读取和符加

  示例代码如下:

#include <stdio.h>

FILE* stream=fopen("/data/data/com.example.hellojni/test.txt","w");

if(NULL==stream){

MY_LOG_VERBOSE("can not open!");

}else{

//使用流

//关闭流

   }

写入流-----------------------------------------------------------------------------------------------

//向流中写入数据块

size_t fwrite(const void* data,size_t size,size_t count,FILE* stream);

示例代码如下:

//使用fwrite向流中写入数据块

char data[] = { 'h''e''l''l''o''\n' };

size_t count = sizeof(data); //数据块长度

 

//向流中写入数据

if (count != fwrite(data, sizeof(char), count, stream)) {

MY_LOG_VERBOSE("fwrite error!");

else {

MY_LOG_VERBOSE("fwrite success!");

}

 

 

 

向流中写入字符序列

Int fputs(const char* data,FILE* stream);

 

//向流中写入字符串序列

if (EOF == fput("hello\n", stream)) {

MY_LOG_VERBOSE("fput error!");

else {

MY_LOG_VERBOSE("fput success!");

}

 

 

向流中写入单个字符

Int fputc(int c,FILE* stream);

//向流中写入单个字符

char c = 'c';

if (c != fputc(c, stream)) {

MY_LOG_VERBOSE("fputc error!");

else {

MY_LOG_VERBOSE("fputc success!");

}

//向流中写入有格式的字符串

Int fprintf(FILE* stream,const char* format,...);

 

//向流中写入有格式的数据

if (0 > fprintf(stream, "the %s is %d""number", 2)) {

MY_LOG_VERBOSE("fprintf error!");

else {

MY_LOG_VERBOSE("fprintf success!");

}

刷新缓冲区

Int fflush(FILE* stream);

 

 

流的读取--------------------------------------------------------------------------------------

从流中读取数据块

Size_t fread(void* data,size_t size,size_t count,FILE* stream);

 

//从流中读取四个字符的块数据

char buffer[5];

size_t tmpSize = 4;

if (tmpSize != fread(buffer, sizeof(char), tmpSize, stream)) {

MY_LOG_VERBOSE("fread error!");

else {

//以空结尾

buffer[4] = NULL;

//输出缓冲区到日志文件

MY_LOG_INFO("read: %s", buffer);

}

 

从流中读取字符序列

Char* fgets(char* buffer,int count,FILE* stream);

//从流中读取字符串序列

char sBuffer[1024];

if (NULL == fgets(buffer, 1024, stream)) {

MY_LOG_VERBOSE("fgets error!");

else {

MY_LOG_INFO("fgets read: %s", buffer);

}

从流中读取单个字符

Int fgetc(FILE* stream);

//从流中读取单个字符

unsigned char ch;

int result;

result = fgetc(stream);

if (EOF == result) {

MY_LOG_VERBOSE("fgetc error!");

else {

ch = (unsigned char) result;

MY_LOG_INFO("fgetc read: %s", ch);

}

 

 

 

从流中读取格式数据

Int fscanf(FILE* stream,const char* format,...);

//从流中读取格式字符串

char s[5];

int i;

if (2 != fscanf(stream, "the %s is %d", s, &i)) {

MY_LOG_VERBOSE("fscanf error!");

}

 

 

检查文件结尾

Int feof(FILE* stream);

//检查文件结尾

char checkBuffer[1024];

while (0 == feof(stream)) {

fgets(buffer, 1024, stream);

MY_LOG_INFO("fgets read: %s", checkBuffer);

}

 

 

 

 

 

搜索位置------------------------------------------------------------

Int fseek(FILE* stream,//流指针

          long offset,//相对偏移量

          int whence);//位置参数

位置参数类型:

SEEK_SET:偏移量相对于流的开头

SEEK_CUR:偏移量相对于当前位置

SEEK_END:偏移量相对于流结尾

 

示例代码如下:

fputs("abcd", stream);

//倒回四个流字节

fseek(stream, -4, stream);

//用efgh重写abcd

fputs("efgh", stream);

 

错误检查----------------------------------------------------------------------------------

Int ferror(FILE* stream);

//检查错误

if(0!=ferror(stream)){

//前一次请求中产生错误

}

 

关闭流--------------------------------------------------------------------------------------

Int fclose(FILE* stream);

//关闭流

if (0 != fclose(stream)) {

MY_LOG_VERBOSE("fclose error!");

}

 

 

 

与进程交互

   执行shell命令 (可以用systemshell传递命令)

  #include <stdlib.h>

  //用系统函数执行shell命令

int sysResult;

//在应用程序中新建目录

sysResult=system("mkdir /data/data/com.example.hellojni/temp");

if(-1==sysResult || 127==sysResult){

MY_LOG_VERBOSE("shell option failed!");

}

 

 

 

  与子进程通信

  FILE *popen(const char* command,const char* type);

 //用ls打开一个通道并打印输出

FILE* tmpStream;

tmpStream = popen("ls""r");

if (NULL == stream) {

MY_LOG_ERROR("unable to execute the command!");

else {

char buffer[1024];

int status;

//从命令行读取每一行

while (NULL != fgets(buffer, 1024, stream)) {

MY_LOG_INFO("read: %s", buffer);

}

//关闭通道并获取其状态

status = pclose(stream);

MY_LOG_INFO("process exited with status %d", status);

}

 

 

系统配置

Android 的系统属性是以键值对的方式保存,bionic提供了一组函数来查询

  需要包含的头文件

  #include <sys/system_properties.h>

  属性名最大值 PROP_NAME_MAX

  属性值最大值 PROP_VALUE_MAX

 

通过名称获取系统属性值

Int __system_property_get(const char* name,char* value);

//通过名称获取系统属性值

char paramValue[PROP_VALUE_MAX];

if (0 == __system_property_get("ro.product.model", paramValue)) {

MY_LOG_INFO("system properties can not find or it is null!");

else {

MY_LOG_INFO("product model: %s", paramValue);

}

 

通过名称获取系统属性值

Const prop_info* __system_property_find(const char* name);

 

//通过名移获取系统属性

const prop_info* property;

property = __system_property_find("ro.product.model");

if (NULL == property) {

MY_LOG_INFO("system property can not find!");

else {

char name[PROP_NAME_MAX];

char value[PROP_VALUE_MAX];

//取得系统属性名称和值

if (0 == __system_property_read(property, name, value)) {

MY_LOG_INFO("%s is empty", name);

else {

MY_LOG_INFO("%s is %s", name,value);

}

}

 

 

用户和组

需要头文件:

  #include <unistd.h>

获取应用程序用户组

//使用getuid获得应用程序的用户id

uid_t uid;

uid = getuid();

MY_LOG_INFO("application user id is %u", uid);

//使用getgid获得应用程序组id

gid_t gid;

gid = getgid();

MY_LOG_INFO("application group id is %u", gid);

 

获取应用程序用户名

//获取应用程序用户名

char* username;

username = getlogin();

MY_LOG_INFO("Application user name is %s", username);

 

 

进程间通信

 Bionic 暂不支持进程间通信

你可能感兴趣的:(android_c++ 高级编程NDK学习笔记四)