win7下java通过JNI调用C代码

1 篇文章 0 订阅
1 篇文章 0 订阅

昨天讲了 java 使用 Jnative.jar 包方式调用c代码,后来又看了使用JNI的方式,这里再做个小结。
网上例子demo讲解很多,但是都不详细,简直误人子弟,也是醉了!!!还是要自己研究。
1、其实Jnative方式是对JNI进行了一层封装,便于使用,直接通过接口就可以了,程序员用起来方便啊。我发现xxx.c 文件里面的是使用C语言编写的,而使用JNI 实现的xxx.c 是用c++编写的。反正对c、c++来说,我是个菜鸟,大概知道就行了。

2、开始写demo
首先需要安装环境啊,我没有vc++环境,使用的是mingw,安装这个是为了可以用命令 g++/gcc 来编译c文件。

g++ :   .c/.c++ 命令
gcc: 最好只针对.c文件

命令参考:
http://blog.csdn.net/u013378306/article/details/52424826
科普:
xxx.h 头文件
xxx.c c/c++语言编写的源代码
xxx.cpp 这个里面的代码最好是c++编写的
xxx.o 链接文件
xxx.dll 生成dll文件
xxx.exe 可执行文件
1)写java 代码

package com.test;

public class TestNative {
    public native void sayHello();

    static {
        System.loadLibrary("Hello");// 加载生成的dll文件
    }

    public static void main(String[] args) {
        new TestNative().sayHello();
    }
}

2)java代码生成.h 的头文件
javah com.test.TestNative
回车后生成:com_test_TestNative.h

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

#ifndef _Included_com_test_TestNative
#define _Included_com_test_TestNative
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_test_TestNative
 * Method:    sayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_test_TestNative_sayHello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

这个一看就知道是C++代码!!!

3)编写实现.h头文件的 .c代码com_test_TestNative.c

#include "jni.h"
#include "com_test_TestNative.h"

JNIEXPORT void JNICALL Java_com_test_TestNative_sayHello(JNIEnv *env,
        jobject obj) {
    puts("c++");
    return;
}

注:
这里注意需要把jdk里面的jni.h、jni_md.h 2个文件拷贝过来,估计是C语言添加的引用。
C++输出方式有2种:
PUTS输出和COUT输出
但是网上demo都是用cout,这个需要
#include <iostream.h>
文件,我一直报错

fatal error: iostream.h: No such file or directory
     #include <iostream.h>
                            ^
compilation terminated.

尼玛,貌似需要vc环境???
后来改成puts命令,不需要#include<iostream.h>

这里我认为有错。c++代码(xxx.cpp文件)应该使用这种方式

#include<iostream>
using namespace std;  

所以如果你要是使用cout 方式输出,需要使用#include <iostream>
using namespace std;

文件后缀必须修改成
xxx.cpp (C++语言)

代码修改:

#include <iostream>  
using namespace std;  
//#include "jni.h"
#include "com_test_TestNative.h"
JNIEXPORT void JNICALL Java_com_test_TestNative_sayHello(JNIEnv *env,
        jobject obj) {
    //puts("c++");
    cout<<"helloworld"<<endl;  
    return;
}

4)有了
com_test_TestNative.c 文件认为可以和Jnative一样,刚开始使用
C:\Users\lihui20\Downloads\mingw>gcc -Wall -shared C:\Users\lihui20\Downloads\mi
ngw\com_test_TestNative.c -o Hello.dll

命令来一次性将
com_test_TestNative.c文件生成Hello.dll文件,
但是后来发现运行时候一直报错。
Exception in thread “main” java.lang.UnsatisfiedLinkError: com.test.TestNative.sayHello()V
at com.test.TestNative.sayHello(Native Method)
at com.test.TestNative.main(TestNative.java:11)
不知道为什么????

百度发现需要分2步:
.c—> .o
C:\Users\lihui20\Downloads\mingw>gcc -c C:\Users\lihui20\Downloads\mingw\com_tes
t_TestNative.c

.o—> .dll
C:\Users\lihui20\Downloads\mingw> gcc -Wl,–add-stdcall-alias -shared -o Hello.dll C:\Users\lihui20\Downloads\mingw\com_test_TestNative.o

注意:如果你是.cpp文件格式,生成.o文件后,必须使用g++,生成 .dll文件

D:\test>g++   -Wl,-add-stdcall-alias -shared -o Helloworld.dll com_test_TestNative.o

如果你使用gcc报错如下:

D:\test>gcc -Wl,--add-stdcall-alias -shared -o Hello.dll com_test_TestNative.o
com_test_TestNative.o:com_test_TestNative.cpp:(.text+0x11): undefined reference
to `std::cout'
com_test_TestNative.o:com_test_TestNative.cpp:(.text+0x16): undefined reference
to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::cha
r_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*
)'
com_test_TestNative.o:com_test_TestNative.cpp:(.text+0x1d): undefined reference
to `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char
_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)'
com_test_TestNative.o:com_test_TestNative.cpp:(.text+0x24): undefined reference
to `std::ostream::operator<<(std::ostream& (*)(std::ostream&))'
com_test_TestNative.o:com_test_TestNative.cpp:(.text+0x3c): undefined reference
to `std::ios_base::Init::~Init()'
com_test_TestNative.o:com_test_TestNative.cpp:(.text+0x5d): undefined reference
to `std::ios_base::Init::Init()'
collect2.exe: error: ld returned 1 exit status

把生成的Hello.dll 文件放在项目最外层目录:
E:\ecplicespace\FileExplorer-master\TestJNIdemo

运行:
c++

这里java使用jni方式调用c++代码成功。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值