code::Blocks生成的dll 在 java jni 调用遇到的问题
Test.java
__________________________________
public class Test
{
public static native void p();
public static void main(String[] args)
{
System.loadLibrary("TestDll");
p();
}
}
javac Test.java
javah -jni Test //命令生成的test.c头文件
/* DO NOT EDIT THIS FILE - it is machine generated */
#include "jni.h"
/* Header for class Test */
#ifndef _Included_Test
#define _Included_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Test
* Method: p
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_Test_p
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
testdll.c (将 c:\jdk\bin下面的 jni.h 和 jni_md.h 复制到当前c程序的文件夹里)
________________________________
#include "jni.h"
#include "test.h"
#include <stdio.h>
JNIEXPORT void JNICALL Java_Test_p(JNIEnv *env, jobject obj)
{
printf("Hello world!\n");
return;
}
用code::Blocks生成的dll,使用DLL Export Viewer查看其函数名是Java_Test_p@8。
cmd> java Test 抛出错误:
java.lang.UnsatisfiedLinkError: Test.p()V
___________________________________________
解决的第1种方法:
在testdll.h文件中把"Java_Hello_p"函数前的"JNICALL"去掉,重编dll就能测试通过。(注: #define JNICALL __stdcall),网上的查到的资料如下:
HTML code
stdcall的调用约定意味着:1)参数从右向左压入堆栈,2)函数自身修改堆栈 3)函数名自动加前导的下划线,后面紧跟一个@符号,其后紧跟着参数的尺寸。
___________________________________________
解决的第2种方法:@silenceburn (http://topic.csdn.net/u/20110216/15/d85cf526-beb9-4a36-b6c2-7ade7f1eb01d.html)
正好手边有codeBlocks,就测试了一下,的确会有LZ说的问题,
放狗搜了搜,是因为JNI想要VC风格的函数声明,但是CodeBlocks默认的GCC编译器生成的是GCC风格的
需要用编译选项修改生成风格,8L的兄弟说的是对的。
修改的位置在CodeBlocks的工程右键properties - Build Targets - Build Options - Linker Setting - Other Linker Options ,加入 -Wl,--kill-at 即可。我在我本机已经测试通过。
___________________________________________
在测试通过java传字符串到c写的dll时,发现在c程序中打印出来的中文会出现乱码情况,在百度搜索后找到一个解决方法:
#include "jni.h"
#include "test.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
char* jstringToWindows( JNIEnv *env, jstring jstr );
jstring WindowsTojstring( JNIEnv* env, char* str );
JNIEXPORT void JNICALL Java_Test_p(JNIEnv *env, jobject obj)
{
printf("Hello world!\n");
return;
}
//通过java传字符串过来
JNIEXPORT void JNICALL Java_Test_abcd(JNIEnv *env, jobject obj, jstring p)
{
const char * str = jstringToWindows( env, p );
printf( "%s\n" , str);
/*
如果把上句改为下句,C接收Java字符串时将出现乱码:
//const char* str = (*env)->GetStringUTFChars(env, p, 0);
//printf("%s",str);
*/
}
//需要用一下2个函数做编码格式转换
char* jstringToWindows( JNIEnv *env, jstring jstr )
{
int length = (*env)->GetStringLength(env,jstr );
const jchar* jcstr = (*env)->GetStringChars(env,jstr, 0 );
char* rtn = (char*)malloc( length*2+1 );
int size = 0;
size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );
if( size <= 0 )
return NULL;
(*env)->ReleaseStringChars(env,jstr, jcstr );
rtn[size] = 0;
return rtn;
}
jstring WindowsTojstring( JNIEnv* env, char* str )
{
jstring rtn = 0;
int slen = strlen(str);
unsigned short* buffer = 0;
if( slen == 0 )
rtn = (*env)->NewStringUTF(env,str );
else
{
int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );
buffer = malloc( length*2 + 1 );
if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )
rtn = (*env)->NewString( env, (jchar*)buffer, length );
}
if( buffer )
free( buffer );
return rtn;
}
code::Blocks生成的dll 在 java jni 调用遇到的问题的更多相关文章
- Code::Blocks生成的EXE文件执行错误解决:The program can't start because libgcc_s_dw2-1.dll is missing
想用C++弄个简单东东,看有没有可行性, 开发软件,微软的太大太肿,就选用了Code::Blocks. 测试HELLO时,在工程环境中没问题的,但生成的EXE执行有问题, 报什么 libgcc_s_d ...
- Java JNI调用c语言的dll测试
最近复习C语言和java语言(10年没用了,温习一下),用JNI调用C语言的dll测试,以前没做过,在网上找了很多,总结如下: 环境:windows 10(64位) + JDK(32位,版本1.7.0 ...
- java jni 调用c语言函数
今日在hibernate源代码中遇到了native关键词,甚是陌生,就查了点资料,对native是什么东西有了那么一点了解,并做一小记. native关键字说明其修饰的方法是一个原生态方法,方法对应的 ...
- java jni 调用c++ opencv代码成功范例
java上建立接口定义 package com.dtk; public class Rec { public native String RecImage(String src); public st ...
- java jni调用
http://www.cnblogs.com/mandroid/archive/2011/06/15/2081093.html
- 使用code::blocks编译windows的dll链接库
因为机子上没有安装Visual Studio,所以找到了一种通过code::blocks编译dll的方式,踩到的坑是code::blocks默认的compiler是32位的,这样编译出的dll也是32 ...
- Java採用JNI调用VC++生成的dll(Java与C++交互)
应项目需求,须要android调用java,java再调用C++实现android一个图片匹配的功能,我们作为java组须要和C++和Android进行交互.以下是java和C++採用JNI的方式进行 ...
- Eclipse、MinGW、JNI编写C++生成dll, Java端调用的完整示例(附java.lang.UnsatisfiedLinkError解决方法)
Eclipse.MinGW.JNI编写C++生成dll, Java端调用的完整示例(附java.lang.UnsatisfiedLinkError解决方法) 问题背景:之前的JNI编程都是基于And ...
- Java通过JNI调用dll详细过程(转)
源:Java通过JNI调用dll详细过程 最近项目有这样一个需求,在已有的CS软件中添加一个链接,将当前登录用户的用户名加密后放在url地址中,在BS的login方法里通过解密判断,如果为合法用户则无 ...
随机推荐
- 基于RC4加密算法的图像加密
基于RC4加密算法的图像加密 某课程的一个大作业内容,对图像加密.项目地址:https://gitee.com/jerry323/RC4_picture 这里使用的是RC4(流.对称)加密算法,算法流 ...
- eclipse添加maven环境
一.打开eclipse,选择Window->preference,如下图所示 二.Maven-> installation->add,见下图: 三.选择Directory,选择mav ...
- 后台跑包方法 断开ssh程序也能继续执行的方法screen命令
aircrack-ng -w 字典路径 握手包路径 screen -S 001创建会话 screen -ls 列出窗口列表 screen -r 5位数字 进入会话指令 如果会话恢复不了,则是有可能 ...
- S2X环境搭建与示例运行
S2X环境搭建与示例运行 http://dbis.informatik.uni-freiburg.de/forschung/projekte/DiPoS/S2X.html 环境 Maven proje ...
- 《Linux内核设计与实现》 第八周读书笔记 第四章 进程调度
20135307 张嘉琪 第八周读书笔记 第四章 进程调度 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间,进程调度程序可看做在可运行态进程之间分配有限的处理器时间资源的内核子系统.只有 ...
- 同步手绘板——json
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.它基于ECMAScript的一个子集. JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族 ...
- C程序设计实践教学提示
实践教学要点:实验重心应放在实验室之外,重在实验准备 对实验题目的分析是一个复杂的工作,很发时间的,如全部放在实验上机时来完成,是不现实的.(特别是后面实验的难度增大,或实验代码增多的情况下),而且, ...
- Java提高篇(1)封装
三大特性之---封装 封装从字面上来理解就是包装的意思,专业点就是信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独立实体,数据被保护在抽象数据类型的内部,尽可能 ...
- PAT 1036 跟奥巴马一起编程
https://pintia.cn/problem-sets/994805260223102976/problems/994805285812551680 美国总统奥巴马不仅呼吁所有人都学习编程,甚至 ...
- WIN10基于Hyper-V下运行kubernetes入门问题
http://www.cnblogs.com/shanyou/p/8503839.html 安装配置好之后启动,查看ip的方法: minikube status minikube ip 查看仪表盘da ...