如何用cygwin在windows下创建so

最近在研究jni。jni: java native interface。


遇到的问题是如何在windows下打包生成native函数。直接使用helloworld入正题。

1)首先创建HelloWorld.java文件:

class HelloWorld
{
    public native void hello();//创建一个native函数,需要用C实现

    static{
        System.loadLibrary("hello"); //这里加载的库是hello.so或者hello.dll等,我们使用.so
    }

    public static void main(String[] args)
    {
        new HelloWorld().hello();
    }
}

2)将上述文件保存为HelloWorld.java

如下图:

3)打开cygwin(我的平台是win7 64位,cygwin-terminal 64)

进入到存放的目录(下面都是我的文件路径):

$cd /cygdrive/e/android/test

4)通过javac生成.class(java路径配置在这里不描述了)

$javac HelloWorld.java

这样就可以在文件夹下看到HelloWorld.class文件了

5)通过.class生成native要用的.h文件

$javah -jni HelloWorld

注意这里只需要输入HelloWorld即可,自动会调用HelloWorld.class

6)通过5)生成的HelloWorld.h内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloWorld */

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    hello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_hello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

7)由上述源码可以知道,我们要在C中实现函数HelloWorld_hello()。

具体HelloWorld.c实现如下:


#include <stdio.h>

typedef signed long long __int64;

#include <jni.h>
#include "HelloWorld.h"

JNIEXPORT void JNICALL Java_HelloWorld_hello
  (JNIEnv *env, jobject obj){
    printf("Hello World!\n");
}

其中需要补充一下的是,在编译C时出现了很多问题:

首先是jni.h不能被找到,stdio.h也找不到。

jni.h是包含在%JAVA_HOME%\include目录下,而jni.h又包含了jni_md.h,这个文件在%JAVA_HOME%\include\win32里。

如果在cygwin下直接-I"%JAVA_HOME%\include"或者-I"%JAVA_HOME%/include"等是不行的,因为JAVA_HOME只是win7下的环境变量,并不是cygwin下设置的环境变量。

建议直接 -I"/cygdrive/c/Program Files/Java/jdk1.6.0_45/include" -I"/cygdrive/c/Program Files/Java/jdk1.6.0_45/include/win32" 其中jdk的路径是C:\Program Files\Java\jdk1.6.0_45。

编译命令如下:

$gcc -c -I"/cygdrive/c/Program Files/Java/jdk1.6.0_45/include" -I"/cygdrive/c/Program Files/Java/jdk1.6.0_45/include/win32" HelloWorld.c -o hello.o

这个时候提示错误:

错误显示内容是__int64没有定义。这个问题我也不知道该包含哪些库。最简单的办法是直接在HelloWorld.c里加typedef long long __int64;

放的位置有讲究。由错误图片可以看出,是jni_md.h里没有定义__64,故需要在jni.h前定义好typedef.

8)再次执行

$gcc -c -I"/cygdrive/c/Program Files/Java/jdk1.6.0_45/include" -I"/cygdrive/c/Program Files/Java/jdk1.6.0_45/include/win32" HelloWorld.c -o hello.o

可以看到生成了目标文件hello.o

9)接下来就是要将hello.o文件生成.so的动态链接库

命令如下:

$gcc hello.o -shared -fPIC -o libhello.so

建议加入-fPIC生成标准的C++函数库。

执行完成后就可以看到libhello.so了。

至于为什么要用libhello.so,是因为android在System.loadLibrary(“hello”)时自动会查找libhello.so的。

需要深入的话推荐看《深入理解Android》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值