生成so库供Java调用

需求

在上次完成的gpio控制中,把c文件编译成一个so库,供java程序调用.

准备工作

首先在网上查找了大量的资料,然后一步一步的按照网上的教程在linux平台下面走了一边,包括.java文件编译成.class文件,然后生成.h文件,然后用c语言实现该方法即可.大概流程就是这样,觉得很简单.下午往android代码里面添加的时候发现很多问题.下面把详细步骤记录下来.

步骤

平台:展讯的7715,安卓7.0
java代码很简单,直接调用一个方法即可.用的还是HelloWorld示例.

System.loadLibrary(“HelloWorld”); 
class HelloWorld {
    static {
        System.loadLibrary("HelloWorld");   
    }
    private native void greeting();
    public static void main(String[] args) {
        new HelloWorld().greeting();
    } 
}

编译生成.class文件,然后通过javah HelloWorld生成.h文件,然后编写.c文件包含.h文件并实现.h文件里面的方法.

#include "HelloWorld.h"
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/ioctl.h>
#define DEV_IOC_MAGIC '0xee' //定义幻数


#define DEV_IOCPRINT  _IO(DEV_IOC_MAGIC, 1)
#define DEV_IO_HIGH   _IO(DEV_IOC_MAGIC, 2)
#define DEV_IO_LOW    _IO(DEV_IOC_MAGIC, 3)

#define DEV_IOC_MAXNR 3

JNIEXPORT void JNICALL Java_HelloWorld_greeting
  (JNIEnv *env, jobject obj) {
    printf("Hello World!");
    int cmd;
    int fd;
    int choice = 0;
    fd = open("/dev/dsx", O_RDWR);
    if(fd < 0)
        printf("ni  haishi  dabukai  ya !\n");
    /*命令1:打印串口信息*/
    while(1)
    {
        int i=0;

        printf("Please input choice: \n 1: DEV_IOCPRINT; \n 2: DEV_IO_HIGH\n 3: DEV_IO_LOW \n 4: EXIT \n");
        scanf("%d", &choice);
        if(choice == 4)
        {
            printf("gpio test exit\n");
            break;
        }
        switch(choice)
        {
            case 1:
            {
                printf("<--- Call DEV_IOCPRINT --->\n");
                cmd = DEV_IOCPRINT;
                if (ioctl(fd, cmd) < 0)
                {
                    printf("Call cmd MEMDEV_IOCPRINT fail\n");
                }
                break;
            }
            case 2:
            {
                printf("<--- Call DEV_IO_HIGH --->\n");
                cmd = DEV_IO_HIGH;
                if (ioctl(fd, cmd) < 0)
                {
                    printf("Call cmd DEV_IO_HIGH fail\n");
                }
                break;
            }
            case 3:
            {
                printf("<--- Call DEV_IO_LOW --->\n");
                cmd = DEV_IO_LOW;
                if (ioctl(fd, cmd) < 0)
                {
                    printf("Call cmd DEV_IO_LOW fail\n");
                }
                break;
            }
            default:
                break;
        }
        printf("\n\n===================================\n");
    }

}

直接把原来的代码里面的main函数放到了Java_HelloWorld_greeting里面.
本以为这样就可以了,但是编译生成的so库放到开发板里面怎么都不行,经过师傅的讲解以后(下面的步骤很关键哦),在external下面新建一个文件夹,然后把.c文件和.h文件放进来,最重要的是要写一个Android.mk文件.然后编译安卓源代码就可以了.

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

LOCAL_ARM_MODE :=arm

LOCAL_MODULE := **libHelloWorld**//一定要加上lib
LOCAL_SRC_FILES := HelloWorld.c
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(BUILD_SHARED_LIBRARY)

然后编译该目录,会在system/bin下面生成libHelloWorld.so.这个才是最终生成的so文件,把它push进开发板的system/lib目录下面,然后在开发板中运行刚才写的java代码生成的.class就可以了.

感悟

这个任务其实挺简单的,多查资料,实在搞不明白的问问师傅,很快就可以解决.

猜你喜欢

转载自blog.csdn.net/arunboy/article/details/78743178