〖Android〗OK6410a的Android HAL层代码编写笔记
一、编写LED灯的Linux驱动程序代码
之所以使用存在HAL层,是为了保护对硬件驱动过程的逻辑与原理;
所以,残留在Linux驱动层的代码,只保留了基本的读写操作,而不含有关键的逻辑思维;
1. leds_hal_define.h (包含对读写寄存器的宏定义)
#define S3C6410_LEDS_HAL_WRITE_GPMPUD 1
#define S3C6410_LEDS_HAL_WRITE_GPMCON 2
#define S3C6410_LEDS_HAL_WRITE_GPMDAT 3
#define S3C6410_LEDS_HAL_READ_GPMPUD 4
#define S3C6410_LEDS_HAL_READ_GPMCON 5
#define S3C6410_LEDS_HAL_READ_GPMDAT 6
2. s3c6410_leds_hal.h (包含必须的头文件及设备的定义)
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/pci.h>
#include <linux/uaccess.h>
#include <mach/map.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank-m.h> #define DEVICE_NAME "s3c6410_leds_hal"
#define DEVICE_COUNT 1
#define S3C6410_LEDS_MAJOR 0
#define S3C6410_LEDS_MINOR 234
3. s3c6410_leds_hal.c (包含对设备文件读写操作)
#include "s3c6410_leds_hal.h"
#include "leds_hal_define.h" static unsigned char mem[]; /* 第1字节保存寄存器类型,后边4字节保存寄存器的值 */
static int major = S3C6410_LEDS_MAJOR;
static int minor = S3C6410_LEDS_MINOR;
static dev_t dev_number;
static struct class *leds_class = NULL; //字节转换int类型
static int bytes_to_int(unsigned char buf[], int start){
int n=;
n = ((int)buf[start]<<
| (int)buf[start+]<<
| (int)buf[start+]<<
|(int)buf[start+]);
return n;
} //将int转换成bytes
static void int_to_bytes(int n, unsigned char buf[], int start){
buf[start] = n >> ;
buf[start+] = n >> ;
buf[start+] = n >> ;
buf[start+] = n;
} //设备的写操作
static ssize_t s3c6410_leds_hal_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos){
if (copy_from_user(mem, buf, )){
return -EFAULT;
}
else{
int gpm_type = mem[];
switch ( gpm_type ) {
case S3C6410_LEDS_HAL_WRITE_GPMCON:
iowrite32(bytes_to_int(mem,),S3C64XX_GPMCON);
break; case S3C6410_LEDS_HAL_WRITE_GPMPUD:
iowrite32(bytes_to_int(mem,),S3C64XX_GPMPUD);
break; case S3C6410_LEDS_HAL_WRITE_GPMDAT:
iowrite32(bytes_to_int(mem,),S3C64XX_GPMDAT);
break; default:
printk(DEVICE_NAME "\tnot the write type.\n");
break;
}
}
return ;
} //设备的读操作
static ssize_t s3c6410_leds_hal_read(struct file *file, char __user *buf, size_t count, loff_t *ppos){
int gpm_type = mem[];
int gpm_value = ;
switch ( gpm_type ) {
case S3C6410_LEDS_HAL_READ_GPMCON:
gpm_value=ioread32(S3C64XX_GPMCON);
break; case S3C6410_LEDS_HAL_READ_GPMPUD:
gpm_value=ioread32(S3C64XX_GPMPUD);
break; case S3C6410_LEDS_HAL_READ_GPMDAT:
gpm_value=ioread32(S3C64XX_GPMDAT);
break; default:
printk(DEVICE_NAME "\tnot the read type.\n");
break;
}
int_to_bytes(gpm_value, mem, ); /* 转换成byte数组 */
if (copy_to_user(buf, (void*)mem, )){ /* 把数据复制到用户空间 */
return -EFAULT;
}
return ; /* 返回已读数据长度 */
} static struct file_operations dev_fops=
{
.owner = THIS_MODULE,
.read = s3c6410_leds_hal_read,
.write = s3c6410_leds_hal_write
}; static struct cdev leds_cdev; //创建设备文件
static int leds_create_device(void){
int ret = ;
int err = ; cdev_init(&leds_cdev, &dev_fops); /* 初始化cdev成员,与dev_fops连接 */
leds_cdev.owner = THIS_MODULE;
if (major>){ /* 若大于0,选择手动分配 */
dev_number = MKDEV(major, minor);
err = register_chrdev_region(dev_number, DEVICE_COUNT,DEVICE_NAME);
if (err<){
printk(KERN_WARNING "register_chrdev_region() failed\n");
return err;
}
}
else { /* 若主设备号小等于0,使用自动分配设备号 */
err = alloc_chrdev_region(&leds_cdev.dev, , DEVICE_COUNT,DEVICE_NAME);
if (err<){
printk(KERN_WARNING "alloc_chrdev_region() failed\n");
return err;
}
major = MAJOR(leds_cdev.dev); /* 及时保存主设备号 */
minor = MINOR(leds_cdev.dev); /* 及时保存次设备号*/
dev_number = leds_cdev.dev; /* 保存设备号信息*/
}
ret = cdev_add(&leds_cdev, dev_number, DEVICE_COUNT); /* 添加驱动设备 */
leds_class = class_create(THIS_MODULE, DEVICE_NAME); /* 创建类型*/
device_create(leds_class, NULL, dev_number, NULL, DEVICE_NAME); /* 创建设备 */
return ret;
} //驱动初始化函数
static int __init leds_init(void){
int ret;
ret = leds_create_device();
printk(DEVICE_NAME "\tintialized\n");
return ret;
} //驱动卸载函数
static void __exit leds_destroy_device(void){
device_destroy(leds_class, dev_number);
if (leds_class){
class_destroy(leds_class);
}
unregister_chrdev_region(dev_number, DEVICE_COUNT);
return;
} module_init(leds_create_device);
module_exit(leds_destroy_device);
MODULE_AUTHOR("linkscue");
MODULE_DESCRIPTION("leds driver witten via hal");
MODULE_ALIAS("leds driver hal");
MODULE_LICENSE("GPL");
4. Makefile
obj-m := s3c6410_leds_hal.o
PWD := $(shell pwd)
#CROSS_COMPILE ?= arm-none-linux-gnueabi-
#CC := $(CROSS_COMPILE)gcc
#CFLAGS += -static
KPATH := /media/Source/Forlinx/android2.3_kernel_v1.
all:
make -C $(KPATH) M=$(PWD) modules
clean:
rm -rf *.o *.ko *.mod.c Module.* modules.*
在编写好了Linux驱动程序代码之后,把make生成的s3c6410_leds_hal.ko上传至OK6410a并使用insmod安装,继续下一步。
二、编写LED灯的Android HAL层代码
这一层使用的协议并不是GPL,不被强制地开放源代码,这一层,包含了对LED控制过程中的所有的逻辑思维;
在本例子当中,这LED灯的初始化寄存器操作的逻辑,打开或者关闭LED灯时应当向寄存器写入什么数据等等。
1. leds_hal.h (包含必须的头文件及宏定义)
#include <hardware/hardware.h>
#include <fcntl.h>
#include <cutils/log.h> struct led_module_t{
struct hw_module_t hw_module;
}; struct led_control_device_t{
struct hw_device_t hw_device;
int (*set_on)(struct led_control_device_t *dev, int32_t led);
int (*set_off)(struct led_control_device_t *dev, int32_t led);
}; #define LED_HARDWARE_MODULE_ID "led_hal" /*-----------------------------------------------------------------------------
* 编写HAL模块需要的3个非常重要的结构体:
* hw_module_t
* hw_device_t
* hw_module_methods_t
* 位置:hardware/libhardware/include/hardware/hardware.h
*-----------------------------------------------------------------------------*/
2. leds_hal.c (包含对灯控制的所有逻辑思想与操作)
#include "leds_hal.h"
#include "leds_hal_define.h" int dev_file = ; /*-----------------------------------------------------------------------------
* 控制LED开关的通用函数
* led表示灯的序号,从0开始
* on_off表示开(1)、关(0)
*-----------------------------------------------------------------------------*/
int led_on_off(struct led_control_device_t *dev, int32_t led, int32_t on_off){
if (led> && led<){
if (on_off == ){
LOGI("LED stub: set %d on", led);
}
else {
LOGI("LED stub: set %d off", led);
}
unsigned char buf[];
buf[] = S3C6410_LEDS_HAL_READ_GPMDAT; /* 准备要读取 */
write(dev_file, buf, );
read(dev_file, buf, );
buf[] = S3C6410_LEDS_HAL_WRITE_GPMDAT; /* 准备要写入 */ switch ( led ) {
case :
if (on_off == ){
buf[]&=0xFE; /* 1111,1110,GPMDAT最后一位是0 */
}
else if (on_off == ){
buf[]|=0x1; /* 0000,0001,GPMDAT最后一位是1 */
}
break; case :
if (on_off == ){
buf[]&=0xFD; /* 1111,1101 */
}
else if (on_off == ){
buf[]|=0x2; /* 0000,0010 */
}
break; case :
if (on_off == ){
buf[]&=0xFB; /* 1111,1011 */
}
else if (on_off == ){
buf[]|=0x4; /* 0000,0100 */
}
break; case :
if (on_off == ){
buf[]&=0xF7; /* 1111,0111 */
}
else if (on_off == ){
buf[]|=0x8; /* 0000,1000 */
}
break; default:
break;
}
write(dev_file, buf, );
}
else {
LOGI("LED Stub: set led %d on error,no this led", led);
}
return ;
} /*-----------------------------------------------------------------------------
* 打开指定的LED灯
*-----------------------------------------------------------------------------*/
int led_on(struct led_control_device_t *dev, int32_t led){
return led_on_off(dev, led, );
} /*-----------------------------------------------------------------------------
* 关闭指定的LED灯
*-----------------------------------------------------------------------------*/
int led_off(struct led_control_device_t *dev, int32_t led){
return led_on_off(dev, led, );
} /*-----------------------------------------------------------------------------
* 关闭设备函数,HAL模块的事件函数之一
*-----------------------------------------------------------------------------*/
int led_device_close(struct hw_device_t *device){
//强行转换成 led_control_device_t
struct led_control_device_t *ctx = (struct led_control_device_t*)device;
if (ctx){
free(ctx); /* 释放设备 */
}
close(dev_file);
return ;
} /*-----------------------------------------------------------------------------
* 初始化GPMCON,GPMPUD寄存器
*-----------------------------------------------------------------------------*/
static void leds_init_gpm(){
int tmp = ;
unsigned char buf[]; //初始化寄存器GPMDAT
buf[] = S3C6410_LEDS_HAL_READ_GPMCON;
write(dev_file, buf, );
read(dev_file, buf, );
buf[] |= 0x11; /* 0001,0001 */
buf[] |= 0x11; /* 0001,0001 */
buf[] = S3C6410_LEDS_HAL_WRITE_GPMCON;
write(dev_file, buf, ); //初始化寄存器GPMPUD
buf[] = S3C6410_LEDS_HAL_READ_GPMPUD;
write(dev_file, buf, );
read(dev_file, buf, );
buf[] |= 0xAA;
buf[] = S3C6410_LEDS_HAL_WRITE_GPMPUD;
write(dev_file, buf, );
} /*-----------------------------------------------------------------------------
* 打开设备的函数
*-----------------------------------------------------------------------------*/
static int led_device_open(const struct hw_module_t *module, const char *name,
struct hw_device_t **device){
struct led_control_device_t *dev;
dev = (struct led_control_device_t *)malloc(sizeof(*dev));
memset(dev, , sizeof(*dev)); /* 清理内存空间 */
dev->hw_device.tag = HARDWARE_DEVICE_TAG; /* HAL设备的标志 */
dev->hw_device.version = ; /* HAL设备的版本号 */
dev->hw_device.module = (struct hw_module_t *)module; /* HAL模块的hw_module_t结构体 */
dev->hw_device.close = led_device_close; /* 关闭设备的函数 */
dev->set_on = led_on; /* HAL的接口函数 */
dev->set_off = led_off; /* HAL的接口函数 */
*device = (hw_device_t *)dev; /* 可替换为*device = &dev->hw_device */
dev_file = open("/dev/s3c6410_leds_hal", O_RDWR);
if (dev_file < ){
LOGI("LED Stub: open /dev/s3c6410_leds_hal fail.");
}
else {
LOGI("LED Stub: open /dev/s3c6410_leds_hal success .");
}
leds_init_gpm; /* 初始化寄存器 */
return ;
} /*-----------------------------------------------------------------------------
* 初始化hw_module_method_t结构体的open成员变量
*-----------------------------------------------------------------------------*/
static struct hw_module_methods_t led_module_methods = {
open: led_device_open
}; /*-----------------------------------------------------------------------------
* 初始化描述HAL模块信息的结构体,此结构体变量名必须是HAL_MODULE_INFO_SYM
*-----------------------------------------------------------------------------*/
struct led_module_t HAL_MODULE_INFO_SYM = {
hw_module:
{
tag:HARDWARE_MODULE_TAG, /* 初始化模块标志 */
version_major:, /* 模块的主版本号 */
version_minor:, /* 模块的次版本情 */
id:LED_HARDWARE_MODULE_ID, /* 初始化模块的ID,通过ID找到此模块 */
name:"Sample LED HAL Stub", /* 初始化模块的名称 */
author:"linkscue", /* 初始化模块的作者 */
methods:&led_module_methods, /* 初始化模块的open函数指针 */
}
};
3. Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) LOCAL_PRELINK_MODULE := false
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_SRC_FILES := leds_hal.c
LOCAL_MODULE :=led_hal.default
LOCAL_MODULE_TAGS := eng
include $(BUILD_SHARED_LIBRARY)
在Android源代码目录下,创建一个 hardware/leds_hal(名字和路径可以随意,当然也可以放在device目录上对应的设备上);
把源代码 Android.mk leds_hal.c leds_hal_define.h leds_hal.h 复制至 hardware/leds_hal 目录下(可通过ln -s链接);
在配置好编译环境之后,通过 mmm hardware/leds_hal 生成HAL共享库文件 led_hal.default.so(命名与头文件的ID有关);
三、编写调用HAL模块的Service
此模块中一个非常重要的函数是 hw_get_module ,它通过在leds_hal.h中定义的LED_HARDWARE_MODULE_ID找到LED的HAL模块,并取得led_module_t结构体。通过 led_module_t.hw_module.methods.open 函数初始化LED驱动,并通过 open 函数返回 led_control_device_t 结构体,在此结构体中含有我们需要的对LED操作的set_on和set_off函数指针。这一段由于使用了C++和JNI(NDK)编程,阅读起来相对有点晦涩难懂,不过编程量相对也比较少,只需要两文件即可。
1. LedHalService.cpp (主要的源代码文件)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <jni.h>
#include <leds_hal.h> struct led_control_device_t *led_hal_device = NULL; /*-----------------------------------------------------------------------------
* JNI函数,打开指定的LED
*-----------------------------------------------------------------------------*/
static jboolean led_setOn(JNIEnv *env, jobject thiz, jint led){
LOGI("Led HAL JNI: led_setOn() is invoked.");
if (led_hal_device == NULL){
LOGI("LED HAL JNI: led_hal_device was not fetched correcttly.");
return -;
}
else {
return led_hal_device->set_on(led_hal_device, led);
}
} /*-----------------------------------------------------------------------------
* JNI函数,关闭指定的LED
*-----------------------------------------------------------------------------*/
static jboolean led_setOff(JNIEnv *env, jobject thiz, jint led){
LOGI("Led HAL JNI: led_setOff() is invoked.");
if (led_hal_device == NULL){
LOGI("LED HAL JNI: led_hal_device was not fetched correcttly.");
return -;
}
else {
return led_hal_device->set_off(led_hal_device, led);
}
} static inline int led_control_open(const struct hw_module_t *module,
struct led_control_device_t **device){
/*
* 调用led_module_t.hw_module.methods.open进行一系列的初始化工作
* open函数会获取led_control_device_t结构体
*/
return module->methods->open(module, LED_HARDWARE_MODULE_ID,
(struct hw_device_t**) device);
} //JNI函数,此方法通过LED_HARDWARE_MODULE_ID找到HAL模块
static jboolean led_init(JNIEnv *env, jclass clazz){
led_module_t *module;
LOGE("************start find hal************");
LOGE("LED_HARDWARE_MODULE_ID");
if (hw_get_module(LED_HARDWARE_MODULE_ID, (const hw_module_t **) &module) == ){
LOGI("LedService JNI: LED Stub found.");
if (led_control_open(&module->hw_module, &led_hal_device) == ){
LOGI("LedService JNI: Got LED operations.");
return ;
}
}
LOGE("LedService JNI: Got LED operations failed.");
return -;
} //定义JNI函数的映射
static const JNINativeMethod methods[] = {
{ "_init", "()Z", (void*) led_init },
{ "_seton", "(I)Z" ,(void *) led_setOn },
{ "_setoff", "(I)Z", (void *) led_setOff },
}; /*-----------------------------------------------------------------------------
* Java数据类型在JNI中的描述符:
* boolean Z
* byte B
* char C
* short S
* int I
* long J
* float F
* double D
*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------
* Java复杂类型在JNI的描述符:
* String "Ljava/lang/String;"
* int[] "[I"
* Object[] "[Ljava/lang/Object;"
* 小技巧:
* [ 表示数组,比如byte[]在JNI中是"[B"
* V 表示未返回任何值即void,比如void method(int a)的返回值是"(I)V"
*-----------------------------------------------------------------------------*/ //将JNI程序库与Java类绑定
int register_led_hal_jni(JNIEnv *env){
//必须由此类调用当前的JNI程序库
static const char *const kClassName = "mobile/android/leds/hal/service/LedHalService";
jclass clazz;
clazz = env->FindClass(kClassName); /* 获取LedHalService类的jclass对象 */
if (clazz == NULL){
LOGE("Can't find class %s", kClassName);
return -;
} /*
* 将此函数注册至LedHalService类当中的一个方法
* sizeof(methods) / sizeof(methods[0]) 用于计算methods的长度
*/
if (env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[])) != JNI_OK){
LOGE("Failed register methods for %s \n", kClassName);
return -;
}
return ;
} //自动调用JNI_OnLoad函数,用于初始化JNI模块
jint JNI_OnLoad(JavaVM *vm, void *reserved){
JNIEnv *env = NULL;
jint result = -;
/*
* JNI_VERSION_1_4表明只能在JSE1.4版本以上才能使用
*/
if (vm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK){
LOGE("GetEnv failed!");
return result;
}
register_led_hal_jni(env);
return JNI_VERSION_1_4;
}
2. Android.mk
#Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := eng
LOCAL_MODULE := led_hal_jni #指定Service程序库的存放路径(指编译出来的.so存放的地方)
LOCAL_MODULE_PATH := /home/scue/work/androidexplorer/led_hal/leds_hal/leds_hal_jni
LOCAL_SRC_FILES := \
LedHalService.cpp #指定共享库的位置
LOCAL_SHARED_LIBRARIES := \
libandroid_runtime \
libcutils \
libhardware \
libhardware_legacy \
libnativehelper \
libsystem_server \
libutils \
libui \
libsurfaceflinger_client #指定头文件的位置
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
hardware/leds_hal #指定预链接模式
LOCAL_PRELINK_MODULE := false include $(BUILD_SHARED_LIBRARY)
把 Android.mk LedHalService.cpp放至同一目录(/home/scue/work/androidexplorer/led_hal/leds_hal/leds_hal_jni);
配置好Android编译环境之后,使用命令 mmm -B /home/scue/work/androidexplorer/led_hal/leds_hal/leds_hal_jni 编译;
mmm 表示编译指定目录的中的内容
-B 表示强制编译其中的内容(即使源代码.cpp文件没有任何改变)
小技巧:
可以不用把/home/scue/work/androidexplorer/led_hal/leds_hal/leds_hal_jni移至Android源代码目录下亦可编译
(未完待续)..
注:本文大部分代码摘取自某本书的源程序代码。
〖Android〗OK6410a的Android HAL层代码编写笔记的更多相关文章
- Android如何完全调试framework层代码
1 之前写过一篇文章:<Android实现开机调试system_process> 2 google的eclipse插件ADT的已经能够很方便的调试Android的apk了,但是调试的时候应 ...
- 【Android】Sensor框架HAL层解读
Android sensor构建 Android4.1 系统内置对传感器的支持达13种,他们分别是:加速度传感器(accelerometer).磁力传感器(magnetic field).方向传感器( ...
- android 广播,manifest.xml注册,代码编写
1.种 private void downloadBr(File file) { // 广播出去,由广播接收器来处理下载完成的文件 Intent sendIntent = new Intent ...
- caffe卷积层代码阅读笔记
卷积的实现思想: 通过im2col将image转为一个matrix,将卷积操作转为矩阵乘法运算 通过调用GEMM完毕运算操作 以下两个图是我在知乎中发现的,"盗"用一下,确实非常好 ...
- Android HAL层与Linux Kernel层驱动开发简介
近日稍微对Android中的驱动开发做了一些简要的了解. HAL:Hardware Abstract Layer 硬件抽象层,由于Linux Kernel需要遵循GPL开源协议,硬件厂商为了保护自己硬 ...
- Android native进程间通信实例-binder篇之——HAL层访问JAVA层的服务
有一天在群里聊天的时候,有人提出一个问题,怎样才能做到HAL层访问JAVA层的接口?刚好我不会,所以做了一点研究. 之前的文章末尾部分说过了service call 可以用来调试系统的binder服务 ...
- Android Hal层简要分析
Android Hal层简要分析 Android Hal层(即 Hardware Abstraction Layer)是Google开发的Android系统里上层应用对底层硬件操作屏蔽的一个软件层次, ...
- 在Ubuntu为Android硬件抽象层(HAL)模块编写JNI方法提供Java访问硬件服务接口(老罗学习笔记4)
在上两篇文章中,我们介绍了如何为Android系统的硬件编写驱动程序,包括如何在Linux内核空间实现内核驱动程序和在用户空间实现硬件抽象层接口.实现这两者的目的是为了向更上一层提供硬件访问接口,即为 ...
- 为Android硬件抽象层(HAL)模块编写JNI方法提供Java访问硬件服务接口
在上两篇文章中,我们介绍了如何为Android系统的硬件编写驱动程序,包括如何在Linux内核空间实现内核驱动程序和在用户空间实现硬件抽象层接 口.实现这两者的目的是为了向更上一层提供硬件访问接口,即 ...
随机推荐
- react-native开发总结
项目地址:http://liu12fei08fei.github.io/blog/41react-native.html 说明 • 项目总结代码地址 • 从项目开始启动(2018-07-02)到项目进 ...
- 【JVM】调优笔记3-----JVM参数配置 JDK1.8
一.关于JVM参数配置,有多种途径. 1.在tomcat中直接配置的 打开tomcat的安装目录, 在bin下修改catalina.bat文件 添加如下: set "JAVA_OPTS=-X ...
- pytest文档15-使用自定义标记mark
前言 pytest可以支持自定义标记,自定义标记可以把一个web项目划分多个模块,然后指定模块名称执行.app自动化的时候,如果想android和ios公用一套代码时, 也可以使用标记功能,标明哪些是 ...
- win7下安装配置ftp服务器
1. win7操作系统自带了ftp组件,所以不需要另外下载.只需要在控制面板中,添加或删除组件中启用即可. 2. 在管理上,ftp和iis是属于同一个目录的.ftp也可以算是internet info ...
- VMware虚拟机的三种联网方法及原理
VMware虚拟机的三种联网方法及原理 博客分类: 操作系统 虚拟机Vmware互联网网络应用网络协议 一.Brigde——桥接 :默认使用VMnet0 1.原理: Bridge 桥"就 ...
- 玩转kafka
http://zookeeper.apache.org/releases.html#download http://kafka.apache.org/downloads.html(下载最新 二进制版本 ...
- 快速近似最近邻搜索库 FLANN - Fast Library for Approximate Nearest Neighbors
What is FLANN? FLANN is a library for performing fast approximate nearest neighbor searches in high ...
- C++中new的用法及显示调用析构函数
最近被问到了C++内存池的问题,其中不免涉及到在指定内存地址调用对象构造函数以及显示调用对象析构函数的情况. C++中new的用法 new是C++中用于动态内存分配的运算符,在C语言中一般使用mall ...
- Linux C Socket编程发送结构体、文件详解及实例
利用Socket发送文件.结构体.数字等,是在Socket编程中经常需要用到的.由于Socket只能发送字符串,所以可以使用发送字符串的方式发送文件.结构体.数字等等. 本文:http://www.c ...
- C语言文件打开方式及说明
ANSI C规定文件打开用函数fopen,关闭为fclose. 1.调用方式通常为: FILE *fp; fp=fopen(文件名, 打开方式); 2.参数说明: 文件名: 形如"myf ...