现在有一个第三方的动态链接库文件mwic.so,现在需要在java中调用此so文件里的函数,故先要生成一个可供java调用的 so(SOTest),具体步骤如下:
1.在java中新建一个空的类SOTest,实现以下代码(假设本次只需要调用SOTest中的run函数):
public class SOTest {
static {
System.load("/home/user/Linux/SOTest.so");
}
public native static int run();
public static void main(String args[]){
SOTest test = new SOTest();
System.out.println("kkkkk"+test.run());
}
}
2.编译刚刚的类,得到.class文件,之后用javah生成头文件(如果不能直接javah SOTest,可以在终端可以先cd进jdk/bin目录下,之后把SOTest.class文件放在该目录下,直接运行javah SOTest)
3.使用c++的开发工具(我这里使用的是geany)新建一个cpp文件SOTest.cpp,并把刚刚得到的SOTest.h文件放到该目录下,并实现cpp里的代码
SOTest.h文件代码:
//注意要把“#include <jni.h>” 该成“#include "jni.h"”
#include "jni.h"
/* Header for class SOTest */
#ifndef _Included_SOTest
#define _Included_SOTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: SOTest
* Method: run
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_SOTest_run
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
SOTest.cpp代码:
#include<dlfcn.h>
#include<stdio.h>
#include<stdlib.h>
#include "SOTest.h"
#include<string.h>
#include<iostream>
JNIEXPORT jint JNICALL Java_SOTest_run
(JNIEnv * env, jclass obj)
{
int devid=0;
int result;
bool tag=false;
std::cout<<"aaaaa";
int a=38400;
std::cout<<"===============初始化,获得设备编号================/n";
void* handle = dlopen("/home/user/Linux/mwic.so",RTLD_LAZY);
typedef int (*auto_init)(char*,int);
dlerror();
auto_init AutoInit = (auto_init) dlsym(handle,"auto_init");
const char *dlsym_error = dlerror();
if(dlsym_error){
//cerr<<"can't load symbol.."<<dlsym_error<<'/n';
dlclose(handle);
return -1;
}
devid=AutoInit("/home/user/Linux/star500x",38400);
if(devid>0)
{
std::cout<<"success!/n";
}else
{
std::cout<<"fail!/n";
}
std::cout<<"devid="<<devid<<"/n";
std::cout<<"===============检查是否有卡================/n";
typedef int (*get_status)(int,int *);
dlerror();
get_status GetStatus = (get_status) dlsym(handle,"get_status");
dlsym_error = dlerror();
if(dlsym_error){
dlclose(handle);
return -1;
}
int status;
GetStatus(devid,&status);
if(status==1)
{
std::cout<<"has card!/n";
}else
{
std::cout<<"no card!/n";
}
std::cout<<"===============检查是否4442卡=================/n";
typedef int (*chk_4442)(int);
dlerror();
chk_4442 Chk4442 = (chk_4442) dlsym(handle,"chk_4442");
dlsym_error = dlerror();
if(dlsym_error){
//cerr<<"can't load symbol.."<<dlsym_error<<'/n';
dlclose(handle);
return -1;
}
result = Chk4442(devid);
if(result==0)
{
std::cout<<"4442 card!/n";
}else
{
std::cout<<"not 4442 catrd!/n";
}
std::cout<<"===============读出错计数器====================/n";
typedef int (*rsct_4442)(int,int *);
dlerror();
rsct_4442 Rsct4442 = (rsct_4442) dlsym(handle,"rsct_4442");
dlsym_error = dlerror();
if(dlsym_error){
dlclose(handle);
return -1;
}
int counter;
result=Rsct4442(devid,&counter);
if(result>=0)
{
std::cout<<"count="<<counter<<"/n";
if(counter>1)
{
tag=true;
}
}else
{
std::cout<<"error!/n";
}
if(tag==true)
{
std::cout<<"================校验密码=======================/n";
typedef int (*csc_4442)(int,int,unsigned char *);
dlerror();
csc_4442 Csc4442 = (csc_4442) dlsym(handle,"csc_4442");
dlsym_error = dlerror();
if(dlsym_error){
dlclose(handle);
return -1;
}
unsigned char databuff[20];
unsigned char kk[20];
memcpy(databuff,"/x11/x11/x11",3);
memcpy(kk,"/xff/xff/xff",3);
for(int k=0;k<3;k++)
{
std::cout<<kk[k]<<"/n";
}
std::cout<<"databuff="<<databuff<<"/n";
std::cout<<"kk="<<kk<<"/n";
//unsigned char * data1="0xffffff";
//data1 = (unsigned char*)(const_cast<char*>(""));
result = Csc4442(devid,3,databuff);
//t=&tt;
if(result==0)
{
std::cout<<"password ok!/n";
}else
{
std::cout<<"password wrong!/n";
}
std::cout<<"================写密码:111111==============/n";
typedef int (*wsc_4442)(int,int,unsigned char *);
dlerror();
wsc_4442 Wsc4442 = (wsc_4442) dlsym(handle,"wsc_4442");
dlsym_error = dlerror();
if(dlsym_error){
dlclose(handle);
return -1;
}
unsigned char password[3];
memcpy(password,"/x11/x11/x11",3);
std::cout<<"set password to:"<<password<<"/n";
result=Wsc4442(devid,3,password);
if(result==0)
{
std::cout<<"set password success!/n";
std::cout<<"password="<<password<<"/n";
}else
{
std::cout<<"set password faild!/n";
}
std::cout<<"================读密码=====================/n";
typedef int (*rsc_4442)(int,int,unsigned char *);
dlerror();
rsc_4442 Rsc4442 = (rsc_4442) dlsym(handle,"rsc_4442");
dlsym_error = dlerror();
if(dlsym_error){
dlclose(handle);
return -1;
}
//unsigned char * password=(unsigned char*)(const_cast<char*>("aaa"));
//unsigned char * password;
//unsigned char password[20];
memcpy(password,"aaa",3);
//password="aaaa";
std::cout<<password<<"/n";
result=Rsc4442(devid,3,password);
if(result==0)
{
std::cout<<"read password success!/n";
printf("password=%s/n",password);
}else
{
std::cout<<"read password fiald!/n";
}
std::cout<<"================write data====================/n";
typedef int (*swr_4442)(int,int,int,unsigned char *);
dlerror();
swr_4442 Swr4442 = (swr_4442) dlsym(handle,"swr_4442");
dlsym_error = dlerror();
if(dlsym_error){
dlclose(handle);
return -1;
}
unsigned char data[2000];
memcpy(data,"123456",256-32);
result=Swr4442(devid,32,256-32,data);
if(result==0)
{
std::cout<<"write data success!/n";
std::cout<<"data="<<data<<"/n";
}else{
std::cout<<"write data error!/n";
}
std::cout<<"================read data====================/n";
typedef int (*srd_4442)(int,int,int,unsigned char *);
dlerror();
srd_4442 Srd4442 = (srd_4442) dlsym(handle,"srd_4442");
dlsym_error = dlerror();
if(dlsym_error){
dlclose(handle);
return -1;
}
unsigned char dataread[2000];
result=Srd4442(devid,32,256-32,dataread);
if(result==0)
{
printf("read data success!/n");
printf("data=%s/n",dataread);
}else
{
printf("read data error!/n");
}
}else
{
std::cout<<"can not go on!/n";
}
return 0;
}
4.把jdk/include目录下的jni.h和linux目录下的jni_md.h目录复制到SOTest.cpp同级目录下
在geany中设置编译和生成参数
编译:g++ -Wall -c "%f" -o "%e"
生成:g++ -wl,--kill-at -shared -o "%e".so "%f"
之后编译生成SOTest.so文件
5.把SOTest.so文件放到之前java代码中指定的地方("/home/user/Linux),运行程序,ok!