简体   繁体   English

.c代码的java包装器

[英]java wrapper for .c code

I have the following c code: 我有以下c代码:

test.c test.c的

#include <stdio.h>
#include <math.h>

int add (int a, int b)
{
    a=4;
    b=4;
    return a+b;
}

int add_pointer (int *a, int *b)
{
    printf("values of a,b: %d,%d \n",*a,*b);
return ((*a)+(*b));
}

char* print_hello()
{
    return "hello_world";
}

test.h test.h

#ifndef TEST_H_
#define TEST_H_

int add(int a, int b);
int add_pointer (int *a, int *b);
char *print_hello();

#endif

main.c main.c中

#include "test.h"
#include <stdio.h>
#include <math.h>

int main()
{
    int a,b,c,d;
    char* rez;

    a=5;
    b=2;

    //int *r=&a;
    c= add(a,b);
    d=add_pointer(&a,&b);
    rez=print_hello();

    printf("sum is: %d and : %s %d \n",c,rez,d);
    return 0;
}

test_app.i test_app.i

%module test_app

%{
#include "test.h"
%}

%include "test.h"

I want to create a java wrapper ofer this .c code. 我想创建一个这个.c代码的java包装器。 I would like later to use this wrapper in an android demo. 我想稍后在Android演示中使用这个包装器。

I did the following: 我做了以下事情:

$: swig -java test_app.i

GIVES: 得到:

test_app_wrapper.c
test_app.java
test_appJNI.java
SWIGTYPE_p_int.java 

$: gcc -fpic -c test.c test_app_wrap.c -I /usr/lib/jvm/java-7-openjdk-amd64/include -I /usr/lib/jvm/java-7-openjdk-amd64/include/linux
$: gcc -shared test.o test_app_wrap.o -o libtest_app_wrap.so

UPDATE: 更新:

HelloWorld.java HelloWorld.java

      public class HelloWorld {
    native String print_hello(); /* (1) */
    static {
        System.loadLibrary("test_app_wrap"); /* (2) */
    }
    static public void main(String argv[]) {
        HelloWorld helloWorld = new HelloWorld();
        helloWorld.print_hello(); /* (3) */
    }
}

When running: 运行时:

$: javac HelloWorld.java 
$ java HelloWorld

I have: 我有:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no test_app_wrap in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1856)
    at java.lang.Runtime.loadLibrary0(Runtime.java:845)
    at java.lang.System.loadLibrary(System.java:1084)
    at HelloWorld.<clinit>(HelloWorld.java:4)

What am I doing wrong? 我究竟做错了什么?

It seems you don't understand how jni works, check this tutorial: 看来你不明白jni是如何工作的,请查看本教程:

Calling C code from Java using JNI 使用JNI从Java调用C代码

Your test_app_wrap doesn't exist, to use JNI you have to assign a particular name to your C functions, then make a Java class with native methods to call them ie 你的test_app_wrap不存在,使用JNI你必须为你的C函数分配一个特定的名称,然后使用本机方法创建一个Java类来调用它们,即

native String print_hello();

and, in the Java class, load the native library. 并且,在Java类中,加载本机库。

Then you will create a YourClass Java object and call the print_hello() native method 然后,您将创建一个YourClass Java对象并调用print_hello()本机方法

When you execute swig -java test_app.i , it creates some Java glue classes that you must include in your Java project. 当您执行swig -java test_app.i ,它会创建一些必须包含在Java项目中的Java glue类。 The main interface generated is named test_app.java and looks like this: 生成的主界面名为test_app.java ,如下所示:

public class test_app {
  public static int add(int a, int b) {
    return test_appJNI.add(a, b);
  }

  public static int add_pointer(SWIGTYPE_p_int a, SWIGTYPE_p_int b) {
    return test_appJNI.add_pointer(SWIGTYPE_p_int.getCPtr(a), SWIGTYPE_p_int.getCPtr(b));
  }

  public static String print_hello() {
    return test_appJNI.print_hello();
  }

}

As you can see, it delegates all the calls to test_appJNI , which is also automatically generated, and acts as a glue to the native code (using native methods): 如您所见,它将所有调用委托给test_appJNI ,这也是自动生成的,并充当本机代码的test_appJNI (使用native方法):

public class test_appJNI {
  public final static native int add(int jarg1, int jarg2);
  public final static native int add_pointer(long jarg1, long jarg2);
  public final static native String print_hello();
}

So, you should: 所以,你应该:

  • include both generated .java files in the project 包括项目中生成的.java文件
  • ensure that you load the .so library with System.loadLibrary("test_app_wrap"); 确保使用System.loadLibrary("test_app_wrap");加载.soSystem.loadLibrary("test_app_wrap"); - you already do it - 你已经做到了
  • simply call test_app.print_hello() 只需调用test_app.print_hello()

Also, recommended reading: 21 SWIG and Java section from SWIG manual. 另外,推荐阅读:SWIG手册中的21 SWIG和Java部分。 The Preliminaries and A tour of basic C/C++ wrapping sections explain all the basics quite well. 预备基本C / C ++包装部分的介绍很好地解释了所有基础知识。

The error you get indicates that JVM can't load the .so library. 您获得的错误表明JVM无法加载.so库。 My first question would be if it compiled and linked properly. 我的第一个问题是它是否正确编译和链接。 If you are sure you have libtest_app_wrap.so , it might not be on the path where JVM looks for it (check this - http://www.chilkatsoft.com/p/p_499.asp ). 如果你确定你有libtest_app_wrap.so ,它可能不在JVM寻找它的路径上(请查看 - http://www.chilkatsoft.com/p/p_499.asp )。 Eg for me it was necessary to add -Djava.library.path=. 例如,对我来说,有必要添加-Djava.library.path=. to Java command line: 到Java命令行:

java -Djava.library.path=. HelloWorld

For reference - I've modified your HelloWorld.java file: 供参考 - 我修改了你的HelloWorld.java文件:

public class HelloWorld {
    static {
        System.loadLibrary("test_app_wrap"); 
    }
    static public void main(String argv[]) {
        test_app.print_hello();
    }
}

Hope that helps :) 希望有帮助:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM