前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >2019-01-10 c调用jar包填坑记录

2019-01-10 c调用jar包填坑记录

作者头像
oracle3
发布2022-05-13 08:35:06
7180
发布2022-05-13 08:35:06
举报

折腾了两天总算搞定c调用jar包,其中遇到的问题这里总结一下: 1、起始demo 参考C调用java例子先跑起来 2、开发环境 使用linux虚拟机效率很低,找到了gnuwin32实现在windows下运行Makefile,使用的是https://sourceforge.net/projects/gnuwin32/ ,只需要把 mingw32-make.exe文件改名为make.exe 3、java开发 直接使用eclipse生成一个mvn项目,以这个最简项目开始入手 使用mvn编译出jar给c调用,参考maven将所有的依赖打成一个包,确保依赖没有问题,验证方法:

代码语言:javascript
复制
java -cp mytest.jar com.test.mytest.App

能够执行成功(jar复制到c文件同一个目录,不成功估计是第7条的问题) 4、jar的调用 options.optionString ="-Djava.class.path=.;mytest.jar"; 这个参数里面的分号不能搞错,否则总是找不到java的类 5、java函数返回值只能是string 其他类型一定得不到返回值,只好老老实实把其他类型转换为string返回 6、java函数执行异常返回值也拿不到 好的习惯是给java代码增加try catch,并且打印异常错误,从而能够快速发现问题,否则就是干着急也看不出问题在哪里,5和6两个问题基本耗费了我一天时间才解决 7、jvm.dll找不到的问题 直接把jvm.dll所在的路径添加到path就可以了 8、如果异常出现并显示java的crash堆栈 估计是函数的参数传递错误了,或者少传参数了 9、linux下和windows的区别有两个 编译命令要改一下:

代码语言:javascript
复制
gcc -I/usr/lib/jvm/jdk1.8.0_111/include -I/usr/lib/jvm/jdk1.8.0_111/include/linux -o hello_world hello_world.c -L/usr/lib/jvm/jdk1.8.0_111/jre/lib/amd64/server -ljvm -D__int64="long long" 

另外c代码里面改一句话

代码语言:javascript
复制
options.optionString ="-Djava.class.path=.;mytest.jar";

修改为:

代码语言:javascript
复制
options.optionString ="-Djava.class.path=.:mytest.jar";

这里附上c的代码,java代码就自己脑补

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include<jni.h>

JNIEnv* create_vm(JavaVM **jvm)
{
    JNIEnv* env;
    JavaVMInitArgs args;
    JavaVMOption options;
    args.version = JNI_VERSION_1_6;
    args.nOptions = 1;
    options.optionString ="-Djava.class.path=.;mytest.jar";
    args.options = &options;
    args.ignoreUnrecognized = 0;
    int rv;
    rv = JNI_CreateJavaVM(jvm,(void**)&env, &args);
    if (rv < 0 || !env)
        printf("Unable to Launch JVM%d\n",rv);
    else
        printf("Launched JVM! :)\n");
    return env;
}


void invoke_class(JNIEnv* env)
{
    jclass clazz;
    jmethodID main_method;
    jmethodID square_method;
    jmethodID power_method;
    jint number=20;
    jint exponent=3;
    clazz =(*env)->FindClass(env, "com/test/mytest/App");
    if(clazz == NULL) {
        printf("can't find hello_world_class");
        return;
    }
    // 这里调用main
    main_method =(*env)->GetStaticMethodID(env, clazz, "main","([Ljava/lang/String;)V");
    if(main_method == NULL) {
        printf("can't find main_method\n");
        return;
    }
    (*env)->CallStaticVoidMethod(env,clazz, main_method, NULL);

    // 这里调用public static String abiEncode(String abi, String data)
    jstring str = (*env)->NewStringUTF(env,"{ \"constant\":false,  \"inputs\":[{\"name\":\"i\",\"type\":\"int\"},  {\"name\":\"s\",\"type\":\"string\"},  {\"name\":\"j\",\"type\":\"int\"}],  \"name\":\"f4\",  \"outputs\":[{\"name\":\"i\",\"type\":\"int\"},  {\"name\":\"s\",\"type\":\"string\"},  {\"name\":\"j\",\"type\":\"int\"}],  \"type\":\"fallback\" }");
    printf("jstring str\n");

        jstring str2 = (*env)->NewStringUTF(env,"111, \"aaa\", 222");
    printf("jstring str2\n");

    jmethodID abiEncode_method =
    (*env)->GetStaticMethodID(env, clazz, "abiEncode","(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");

    if (abiEncode_method == NULL) {
        printf("can't find abiEncode_method\n");
        return; /* method not found */
    }


    jstring result = (*env)->CallStaticObjectMethod(env, clazz, abiEncode_method,str,str2);
    printf("jbyteArray arr %x\n",result);
    if (result == NULL) {
        printf("can't call abiEncode_method\n");
        return; /* method not found */
    }
    const char *message = (*env)->GetStringUTFChars(env, result, NULL);
    if (NULL == message) return;
    printf("In C, the returned string is %s\n", message);
    (*env)->ReleaseStringUTFChars(env, result, message);

        (*env)->DeleteLocalRef(env,str2);
        (*env)->DeleteLocalRef(env,str);
        (*env)->DeleteLocalRef(env,clazz);
        
}


int main(int argc,char **argv)
{
    JavaVM *jvm;
    JNIEnv *env;
    env = create_vm(&jvm);
    if(env == NULL)
        return 1;
    invoke_class(env);
    return 0;
}

如果不用Makefile就直接用下面的命令编译:

代码语言:javascript
复制
gcc -I"C:/Program Files/Java/jdk1.8.0_101/include/" -I"C:/Program Files/Java/jdk1.8.0_101/include/win32" -o hello_world hello_world.c -L"C:/Program Files/Java/jdk1.8.0_101/jre/bin/server" -ljvm -D__int64="long long"
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档