Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to create new javacpp presets from Gradle? #65

Closed
shekmun opened this issue Jan 29, 2016 · 19 comments
Closed

How to create new javacpp presets from Gradle? #65

shekmun opened this issue Jan 29, 2016 · 19 comments

Comments

@shekmun
Copy link

shekmun commented Jan 29, 2016

I've read about the wiki of creating new javacpp presets. But I'm faced with some problems.

I've compiled the gsl library for android-arm properly issue#55 and thanks again.

Now I want to use the gsl library. I do as the wiki but I'm not familiar with maven, so I've just add two java files to my project. Say my package path is com.my.project. So I add gsl.java and presets/gsl.java under the com.my.project directory just like the gsl presets.

And since I didn't know what the InfoMapper means, so I just copy all the content of gsl presets. And only create new gsl.java like this:

public class gsl extends com.my.project.presets.gsl {
    static {
        Loader.load();
    }
    public gsl() {
        allocate();
    }
    private native void allocate();
    public static native double gsl_sf_bessel_J0(double x);
}

I just add the gsl_sf_bessel_J0 as a test. And here is the output:

Targeting libs/armeabi-v7a/org/bytedeco/javacpp/gsl.java
Parsing /home/shekmun/android/libs/include/gsl/gsl_types.h
// .... other Parsing ...
Parsing /home/shekmun/android/libs/include/gsl/gsl_statistics_char.h

Exception in thread "main" java.io.FileNotFoundException: libs/armeabi-v7a/org/bytedeco/javacpp/gsl.java (No such file or directory)
    at java.io.FileOutputStream.open0(Native Method)
    at java.io.FileOutputStream.open(FileOutputStream.java:270)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:162)
    at java.io.FileWriter.<init>(FileWriter.java:90)
    at org.bytedeco.javacpp.tools.Parser$1.<init>(Parser.java:2522)
    at org.bytedeco.javacpp.tools.Parser.parse(Parser.java:2522)
    at org.bytedeco.javacpp.tools.Builder.parse(Builder.java:67)
    at org.bytedeco.javacpp.tools.Builder.build(Builder.java:624)
    at org.bytedeco.javacpp.tools.Builder.main(Builder.java:773)

So, why does javacpp look for the gsl.java file under org.bytedeco.javacpp.

I think I must have misunderstood something. Please help me out, thanks.

@saudet
Copy link
Member

saudet commented Jan 29, 2016

If you're just looking to use gsl, a simple pom.xml file like this should work:
https://github.com/bytedeco/javacpp-presets/tree/master/gsl#the-pomxml-build-file
What issues are you having when using it that way?

@shekmun
Copy link
Author

shekmun commented Jan 29, 2016

Well, using gsl is just a test. Since I have got the compiled gsl.so library. In fact I want to compile my own library and use javacpp to connect to it.

@saudet
Copy link
Member

saudet commented Jan 30, 2016

So, what happens when using it the way explained at the URL below?
https://github.com/bytedeco/javacpp-presets/#downloads

@saudet saudet added the question label Feb 6, 2016
@shekmun
Copy link
Author

shekmun commented Feb 16, 2016

Sorry, but I'm on my Spring Festival these days. Sorry for the late reply.

But I'm not looking for the gsl library. What I really need is the way to generate my own presets library for my-own c++ library. And you can assume that I've compiled my-own library into my-own.so. Now I want to call the methods in the my-own.so library. And according to the gsl library, I need two java file, both named my-own.java and one is under my-own folder (like presets/gsl.java).

Now here is my question: how to write these two java files so that I can call methods in java and indirectly in c++.

I've seen something like InfoMapper and public static native methods. What's the right way to write these two files?

@saudet
Copy link
Member

saudet commented Feb 16, 2016

I understand that you are trying to wrap your own library, but what I don't understand is how it differs from something like the presets for gsl. Could you explain for example what you mean by "call methods indirectly in c++"? Could you provide a concrete example of how that might look like? Thanks!

@shekmun
Copy link
Author

shekmun commented Feb 17, 2016

Sorry for my poor expression. "call methods indirectly in c++" just means call c++ through javacpp and nothing else.

What I've done is add the presets/gsl.java and gsl.java into my own project. And if I compile directly, a lot of errors like something undefined came out. Then I remove most part of gsl.java and remain only one method like this:

public class gsl extends com.my.project.presets.gsl {
    static {
        Loader.load();
    }
    public gsl() {
        allocate();
    }
    private native void allocate();
    public static native double gsl_sf_bessel_J0(double x);
}

Then rebuild the project. Now The error is this:

Targeting libs/armeabi-v7a/org/bytedeco/javacpp/gsl.java
Parsing /home/shekmun/android/libs/include/gsl/gsl_types.h
// .... other Parsing ...
Parsing /home/shekmun/android/libs/include/gsl/gsl_statistics_char.h

Exception in thread "main" java.io.FileNotFoundException: libs/armeabi-v7a/org/bytedeco/javacpp/gsl.java (No such file or directory)
    at java.io.FileOutputStream.open0(Native Method)
    at java.io.FileOutputStream.open(FileOutputStream.java:270)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
    at java.io.FileOutputStream.<init>(FileOutputStream.java:162)
    at java.io.FileWriter.<init>(FileWriter.java:90)
    at org.bytedeco.javacpp.tools.Parser$1.<init>(Parser.java:2522)
    at org.bytedeco.javacpp.tools.Parser.parse(Parser.java:2522)
    at org.bytedeco.javacpp.tools.Builder.parse(Builder.java:67)
    at org.bytedeco.javacpp.tools.Builder.build(Builder.java:624)
    at org.bytedeco.javacpp.tools.Builder.main(Builder.java:773)

It's targeting the file libs/armeabi-v7a/org/bytedeco/javacpp/gsl.java and can't find it. That's my problem.

@saudet
Copy link
Member

saudet commented Feb 17, 2016

You'll first need to change the "include" list in the "presets" class to match your own set of include files.

@shekmun
Copy link
Author

shekmun commented Feb 19, 2016

I want to use my own c++ library, but I want to use gsl as a test first. I'll need to learn how to write the gsl.java and presets/gsl.java. And I want to use the gsl function gsl_sf_bessel_J0 as a test. So I didn't change the include head files in presets/gsl.java regardless of the redundancy.

And I realize why it's looking for the libs/armeabi-v7a/org/bytedeco/javacpp/gsl.java:

/**
 * @author Samuel Audet
 */
@Properties(target="org.bytedeco.javacpp.gsl", value={
        @Platform(include={"gsl/gsl_types.h", "gsl/gsl_errno.h",

The annotation "target" will lead the compiler to find the file under libs. So I tried to put the gsl.java and presets/gsl.java into libs. And I package the files into gsl.jar with the javac and jar command:

javac org/bytedeco/javacpp/gsl.java org/bytedeco/javacpp/presets/gsl.java -cp javacpp.jar
jar -cvf gsl.jar org/bytedeco/javacpp/gsl.class org/bytedeco/javacpp/presets/gsl.class

Then I got the gsl.jar file and put it into libs folder. But when install the apk into my phone, an error says bad class file magic (cafebabe) or version came out. After google on this I realize that I need to change the compiler to jdk1.7 (I was using 1.8 before).

In fact I found a easier way to put the java code into libs. I'm using android studio and do as this:

File->New...->New Module...->Select Java Library->OK

In this way the gradle will do the former work automatically. And of course we need to set the jdk to 1.7.

After all these work, I mean putting the gsl.java and presets/gsl.java into a library, I now can call the gsl_sf_bessel_J0 without compile error. But when it runs to this function, it goes wrong.

W/dalvikvm: No implementation found for native Lorg/bytedeco/javacpp/gsl;.gsl_sf_bessel_J0:(D)D
W/System.err: java.lang.UnsatisfiedLinkError: Native method not found: org.bytedeco.javacpp.gsl.gsl_sf_bessel_J0:(D)D
W/System.err:     at org.bytedeco.javacpp.gsl.gsl_sf_bessel_J0(Native Method)

P.S. The libgsl.so and libgslcblas.so is putted in the android module's library folder. And I've added the gsl.jar or gsl java module as dependency of android module.

Compare to the gsl-android-arm.jar, there is one file named libjnigsl.so not generated. So how can I generate the file.

@saudet
Copy link
Member

saudet commented Feb 19, 2016

If you're trying to understand how to write new presets, it'd probably be easier to start with a smaller example such as zlib as used in this tutorial: https://github.com/bytedeco/javacpp-presets/wiki/Create-New-Presets

@shekmun
Copy link
Author

shekmun commented Feb 22, 2016

Ok, I read about the tutorial and checked the pom.xml files of javacpp-presets and gsl. I found I can use gradle instead of maven to do this and I made a little progress that I can generate the libjnigsl.so file.

I'm using the android studio to create a new java module. Using File->New...->New Module...->Select Java Library->OK. And edit the gradle file like this:

apply plugin: 'java'

compileJava.doLast {
    println 'gsl begin'
    javaexec {
        main 'org.bytedeco.javacpp.tools.Builder'
        classpath '/home/shekmun/android/workspace/IWatcher/gsl/libs/javacpp.jar'
        args '-cp', destinationDir,
                '-properties', 'android-arm',
                '-Dplatform.root=/home/shekmun/android/android-ndk-r9d',
                '-Dplatform.compiler=/home/shekmun/android/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc',
                '-Dplatform.includepath=/home/shekmun/android/android-ndk-r9d/sources/cxx-stl/gnu-libstdc++/4.8/include:/home/shekmun/android/android-ndk-r9d/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a/include:/home/shekmun/android/libs/include',
                '-Dplatform.linkpath=/home/shekmun/android/android-ndk-r9d/sources/cxx-stl/gnu-libstdc++/4.8/libs/armeabi-v7a:/home/shekmun/android/libs/lib',
                '-d', '/home/shekmun/android/workspace/IWatcher/gsl/src/main/java'
    }
    println 'gsl done'
}

dependencies {
    compile files('libs/javacpp.jar')
}

Which is very similar to How to use my own compiled library? #55 except the -d parameter. And I realized why the error Exception in thread "main" java.io.FileNotFoundException: libs/armeabi-v7a/org/bytedeco/javacpp/gsl.java (No such file or directory) came since I was setting the -p as libs/armeabi-v7a before.

Now if I rebuild the gsl library, I'll get the libjnigsl.so file under /home/shekmun/android/workspace/IWatcher/gsl/src/main/java.

And I copy the libjnigsl.so and also the gsl.jar to my android module. And then runs it. Now the error is:

W/dalvikvm: JNI WARNING: JNI function FindClass called with exception pending
W/dalvikvm:              in Ljava/lang/Runtime;.nativeLoad:(Ljava/lang/String;Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/String; (FindClass)
W/dalvikvm: Pending exception is:
E/dalvikvm: VM aborting
A/libc: Fatal signal 6 (SIGABRT) at 0x00003e65 (code=-6), thread 15973 (ct.hci.iwatcher)
A/libc: Send stop signal to pid:15973 in void debuggerd_signal_handler(int, siginfo_t*, void*)

@saudet
Copy link
Member

saudet commented Feb 22, 2016 via email

@shekmun
Copy link
Author

shekmun commented Feb 22, 2016

Ok, I found it. Sorry I've been lazy to create the gsl.jar myself. But I used one downloaded from maven which version 1.16-1.1. I should have generated it by myself.

Now I can generate the gsl.jar with gradle like this:

task makejar(type: Copy) {
    from('build/intermediates/bundles/release/')
    into('../downloads/')
    include('classes.jar')
    rename ('classes.jar', 'gsl.jar')
}

makejar.dependsOn(build)

And right click on the makejar and select Run 'gradle:makejar'. Then I can get the gsl.jar under the folder. And I replace the older gsl.jar with my newly one. Now it runs well and I can call the method gsl_sf_bessel_J0(5.0) with return value -0.17759677131433826.

Which is great. Thanks for your patience. And I'm using gradle instead of maven to do all the job. If needed I can add this to the wiki too when I have the time.

Thanks to javacpp and +saudet that help me working easier now.

@saudet
Copy link
Member

saudet commented Feb 23, 2016

Yes more documentation would be welcome, thanks :) A plugin for Gradle would be nice too, if you'd like to make one.

@tmm1
Copy link
Contributor

tmm1 commented Jun 1, 2017

Is it possible to generate the libjni*.so without maven? I created my own preset for a custom library outside the javacpp-presets repository, and was able to use javac to compile the preset, and am was also able to use javacpp.tools.Builder to parse my headers and generate java stubs. But I can't figure out how to compile a native libjni* wrapper for my existing libmy.so so I can actually use the java stubs..

@saudet
Copy link
Member

saudet commented Jun 1, 2017 via email

@tmm1
Copy link
Contributor

tmm1 commented Jun 1, 2017

We just need to call the Builder again on the generated Java "stubs".

Thank you! That's exactly what I was missing.

@saudet
Copy link
Member

saudet commented Dec 15, 2018

BTW, the new Mapping Recipes for C/C++ Libraries guide should be making all this clearer now.
If you see anything missing there though, please update the page!

However, this doesn't resolve issues with Gradle, so a plugin for that would still be welcome.

@saudet
Copy link
Member

saudet commented May 21, 2020

A build plugin for Gradle is now available here:
https://github.com/bytedeco/gradle-javacpp
Enjoy! Please let me know if there's anything missing.

@saudet
Copy link
Member

saudet commented Sep 10, 2020

Gradle JavaCPP 1.5.4 has been released! Please let me know if you try it out and have any issues with it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants