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 调用遇到的问题的更多相关文章

  1. Code::Blocks生成的EXE文件执行错误解决:The program can't start because libgcc_s_dw2-1.dll is missing

    想用C++弄个简单东东,看有没有可行性, 开发软件,微软的太大太肿,就选用了Code::Blocks. 测试HELLO时,在工程环境中没问题的,但生成的EXE执行有问题, 报什么 libgcc_s_d ...

  2. Java JNI调用c语言的dll测试

    最近复习C语言和java语言(10年没用了,温习一下),用JNI调用C语言的dll测试,以前没做过,在网上找了很多,总结如下: 环境:windows 10(64位) + JDK(32位,版本1.7.0 ...

  3. java jni 调用c语言函数

    今日在hibernate源代码中遇到了native关键词,甚是陌生,就查了点资料,对native是什么东西有了那么一点了解,并做一小记. native关键字说明其修饰的方法是一个原生态方法,方法对应的 ...

  4. java jni 调用c++ opencv代码成功范例

    java上建立接口定义 package com.dtk; public class Rec { public native String RecImage(String src); public st ...

  5. java jni调用

    http://www.cnblogs.com/mandroid/archive/2011/06/15/2081093.html

  6. 使用code::blocks编译windows的dll链接库

    因为机子上没有安装Visual Studio,所以找到了一种通过code::blocks编译dll的方式,踩到的坑是code::blocks默认的compiler是32位的,这样编译出的dll也是32 ...

  7. Java採用JNI调用VC++生成的dll(Java与C++交互)

    应项目需求,须要android调用java,java再调用C++实现android一个图片匹配的功能,我们作为java组须要和C++和Android进行交互.以下是java和C++採用JNI的方式进行 ...

  8. Eclipse、MinGW、JNI编写C++生成dll, Java端调用的完整示例(附java.lang.UnsatisfiedLinkError解决方法)

     Eclipse.MinGW.JNI编写C++生成dll, Java端调用的完整示例(附java.lang.UnsatisfiedLinkError解决方法) 问题背景:之前的JNI编程都是基于And ...

  9. Java通过JNI调用dll详细过程(转)

    源:Java通过JNI调用dll详细过程 最近项目有这样一个需求,在已有的CS软件中添加一个链接,将当前登录用户的用户名加密后放在url地址中,在BS的login方法里通过解密判断,如果为合法用户则无 ...

随机推荐

  1. 理解Liang-Barsky裁剪算法的算法原理

    0.补充知识向量点积:结果等于0, 两向量垂直; 结果大于0, 两向量夹角小于90度; 结果小于0, 两向量夹角大于90度.直线的参数方程:(x1, y1)和(x2, y2)两点确定的直线, 其参数方 ...

  2. centos下部署redis服务环境及其配置说明

    Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起,Redis的开发工作由VMware主 ...

  3. 集群环境删除redis指定的key

    1.说明 redis集群上有时候会需要删除多个key,就必须需要登录到每个节点上,而且有可能这个key不在这个节点,这样删除起来就比较麻烦,下面提供一种便捷方式可以实现 2.查看redis集群中的ma ...

  4. 百度之星-day2-1004-二分答案

    由于序列有序,求其中一个最优解,二分答案即可,注意二分时上边界满足才保存 #include<iostream> #include<stdio.h> #include<st ...

  5. Echarts中graph类型的运用求教

    以下是百度Echarts官网上关系图的源码,但是这个关系图的node节点和edge都是静态文件里规定好的,我现在想动态实现,点击其中一个节点A然后新产生一个新节点B,并且有A和B之间的edge,就类似 ...

  6. 基于SSH实现员工管理系统之框架整合篇

    本篇文章来源于:https://blog.csdn.net/zhang_ling_yun/article/details/77803178 以下内容来自慕课网的课程:基于SSH实现员工管理系统之框架整 ...

  7. PAT 1033 旧键盘打字

    https://pintia.cn/problem-sets/994805260223102976/problems/994805288530460672 旧键盘上坏了几个键,于是在敲一段文字的时候, ...

  8. redi集群测试

    redis集群的测试   原文:http://blog.sina.com.cn/s/blog_53b45c4d0102wg10.html 1.测试存取值 客户端连接集群redis-cli需要带上 -c ...

  9. ubuntu解压zip文件

    step1 # 安装解压软件 sudo apt-get install unzip step # 2 解压文件 unzip xxxxx.zip

  10. Oracle面试题(基础篇)

    1. Oracle跟SQL Server 2005的区别? 宏观上: 1). 最大的区别在于平台,oracle可以运行在不同的平台上,sql server只能运行在windows平台上,由于windo ...