JNI – Đối tượng – Phần 2


Được đăng vào ngày 26/12/2016 | 0 bình luận
Đánh giá bài viết

Trong phần này chúng ta sẽ tìm hiểu cách gọi một phương thức Java từ C++.

Gọi một phương thức

Ví dụ chúng ta có lớp Java tên Methods như sau:

class Methods {
    static { System.loadLibrary("Methods"); } 
    private native void method();
    private void hello() {
        System.out.println("Hello World");
    }
 
    public static void main(String args[]) {
        new Methods().method();
    }
}

Phương thức native tên là method(), phương thức này sẽ được gọi qua C++, rồi từ C++ chúng ta gọi lại một phương thức của lớp Methods này là hello().

Chúng ta làm điều đó như sau:

#include "Methods.h"

JNIEXPORT void JNICALL Java_Methods_method (JNIEnv *e, jobject obj){
    jclass cls = e->GetObjectClass(obj);
    jmethodID mid = e->GetMethodID(cls, "hello", "()V");
    e->CallVoidMethod(obj, mid);
}

Việc thực hiện cũng khá đơn giản.

Đầu tiên chúng ta lấy một đối tượng jclass bằng phương thức GetObjectClass().

Sau đó lấy đối tượng jmethodID bằng phương thức GetMethodID(), phương thức này nhận vào đối tượng jclass, tên lớp bằng chuỗi, rồi đến chuỗi mô tả tham số và kiểu trả về. Chuỗi mô tả này có dạng như sau:

"(kiểu_dữ_liệu_tham_số)kiểu_dữ_liệu_trả_về"

Các kiểu dữ liệu có tên như sau:

TÊN KIỂU DỮ LIỆU
Z Boolean
B Byte
C Char
S Short
I Int
J Long
F Float
D Double
L<tên_đẩy_đủ_của_lớp>; Tên đầy đủ của lớp, có đường dẫn package
[<một_trong_các_kiểu_trên> Kiểu mảng

Ví dụ "()V" có nghĩa là phương thức đó không nhận vào tham số nào và có kiểu dữ liệu trả về là void.

Giả sử trong Java có phương thức:

private String println(String);

Thì chúng ta điền là:

"(Ljava/lang/String;)Ljava/lang/String;"

Ví dụ về kiểu mảng:

Java:

public static void main(String[] args);

C++:

"([Ljava/lang/String;)V"

Lưu ý là nếu phương thức nhận vào kiểu void như f(void) thì trong C++ chúng ta không ghi là "(V)I" mà để trống, tức là "()I".

Hello World

Gọi phương thức static

Gọi một phương thức static cũng tương tự như gọi phương thức bình thường, chỉ khác tên hàm gọi.

Ví dụ chúng ta có code Java như sau:

class Methods {
    static { System.loadLibrary("Methods"); } 
    private native void method();
    private static void staticPrintFactorial(int n) {
        if(n >= 17 || n < 1) {
            System.out.println(n + " is too big or too small");
            return;
        }
        int result = 1;
        for(int i = 2; i <= n ; i++) result *= i;
        System.out.println(result);
    }
 
    public static void main(String args[]) {
        new Methods().method();
    }
}

Chúng ta có một phương thức staticstaticPrintFactorial(), phương thức này nhận vào một số nguyên và in ra giai thừa của số đó.

Chúng ta gọi phương thức này bên C++ như sau:

#include "Methods.h"

JNIEXPORT void JNICALL Java_Methods_method (JNIEnv *e, jobject obj){
    jclass cls = e->GetObjectClass(obj);
    jmethodID mid = e->GetStaticMethodID(cls, "staticPrintFactorial", "(I)V");
    e->CallStaticVoidMethod(cls, mid, 10);
    e->CallStaticVoidMethod(cls, mid, 50);
}

Chúng ta cũng lấy đối tượng jclass, jmethodID, ở đây phương thức lấy là GetStaticMethodID(), các tham số vẫn giống như phương thức GetMethod(), để gọi phương thức static thì chúng ta dùng hàm CallStaticVoidMethod(), phương thức này nhận vào đối tượng jclass, đối tượng jmethodID và các tham số.

3628800
50 is too big

Các phương thức tương tự khác có thể gọi là:

STATIC NON STATIC KIỂU DỮ LIỆU
CallVoidMethod() CallStaticVoidMethod() void
CallObjectMethod() CallStaticObjectMethod() jobject
CallBooleanMethod() CallStaticBooleanMethod() jboolean
CallByteMethod()
CallStaticByteMethod() jbyte
CallCharMethod()
CallStaticCharMethod() jchar
CallShortMethod() CallStaticShortMethod() jshort
CallIntMethod() CallStaticIntMethod() jint
CallLongMethod() CallStaticLongMethod() jlong
CallFloatMethod() CallStaticFloatMethod() jfloat
CallDoubleMethod() CallStaticDoubleMethod() jdouble






Trả lời


Lưu ý: bọc code trong cặp thẻ [code language="x"][/code] để highlight code.


Ví dụ:


[code language="cpp"]


    std::cout << "Hello world";


[/code]



Các ngôn ngữ được hỗ trợ gồm: actionscript3, bash, clojure, coldfusion, cpp, csharp, css, delphi, diff, erlang, fsharp, go, groovy, html, java, javafx, javascript, latex, matlab, objc, perl, php, powershell, python, r, ruby, scala, sql, text, vb, xml.

Thư điện tử của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *