Arvanttt

تند و سریع

Arvant

تند و سریع












فراخوانی توابع ++C در جاوا

پنجشنبه, ۲۹ مرداد ۱۳۹۴، ۱۱:۳۱ ب.ظ

مطلب بعدی در ادامه مطالب مربوط به دسترسی به امکانات بومی در cocos2d-x مربوط به فراخوانی توابع ++C  با استفاده از جاواست .

برای این کار دو عمل اصلی انجام میدیم .

ابتدا تابع مورد نظر را به صورت Native در جاوا تعریف می کنیم .

سپس باید بر اساس یک سری قوانین خاص تابع مورد نظر را در ++C پیاده سازی کنیم .

1. فرض بگیرید تابع awesomeCppFunction تابع مورد نظر ماست که می خواهیم از طریق جاوا فراخوانی کنیم برای اینکار ابتدا تابع مورد نظر را به صورت native در درون کلاس جاوایی که می خواهیم تابع سی را فراخوانی کنیم تعریف می کنیم به این صورت :

public static native void awesomeCppFunction();

برای فراخوانی این تابع کافی است که در هر جا که لازم بود همانند سایر توابع جاوا آن را فراخوانی کنیم .

به طور مثال :

package com.myhouse;

class HappyJavaClass {

    public static native void awesomeCppFunction();

    private void myOrdinaryJavaMethod() {
        String a = "Yes, it's pure Java!";

        awesomeCppFunction();
    }

}

2.تعریف تابع سی با در نظر گرفتن قوانین مورد نظر به صورت زیر :

نام تابع باید در بردارنده نام کامل و پکیجی باشد که تابع در آن تعریف شده است به عنوان مثال برای تابع بالا نامی که در نظر گرفته می شود به شکل زیر باشد 

java_com_myhouse_HappyJavaClass_awesomeCppFunction

در حالت کلی تابع به صورت زیر در یک فایل cpp. استفاده می شود .

extern "C"
{
JNIEXPORT void JNICALL Java_com_myhouse_HappyJavaClass_awesomeCppFunction(JNIEnv* env, jobject thiz);
};

JNIEXPORT void JNICALL Java_com_myhouse_HappyJavaClass_awesomeCppFunction(JNIEnv* env, jobject thiz)
{
    // your C++ code goes here
}

 

کد بالا شامل دو بخش می شود  که بخش اول مربوط به معرفی تابع و بخش دوم مربوط به بدنه اصلی تابع است .

دو آرگومان JNIEnv* env, jobject thiz جهت ارسال مقادیر و بازیابی آن ها از طریق جاوا به سی پلاس پلاس مورد استفاده قرار می گیرد.

 

ارسال پارامتر و برگشت مقادیر :

همانند بخش قبلی برای ارسال مقادیر و بازگردانی آنها باید یک سری قوانین را در مورد انواع داده مورد استفاده رعایت کنیم که در جدول زیر آمده است .

به عنوان مثال تابع 

public static native String awesomeCppFunction(int x, boolean y, String z);

که دارای ارگومان ورودی و مقدار بازگشتی است با استفاده از جدول تغیر نوع از جاوا به jni به صورت زیر تعریف می شود  .

جدول تغیر نوع

JNI Types Java Type
void void
jboolean boolean
jbyte byte
jchar char
jshort short
jint int
jlong long
jfloat float
jdouble double
jobject All Java objects
jclass java.lang.Class objects
jstring java.lang.String objects
jobjectArray Array of objects
jbooleanArray Array of booleans
jbyteArray Array of bytes
jshortArray Array of shorts
jintArray Array of integers
jlongArray Array of longs
jfloatArray Array of floats
jdoubleArray Array of doubles
 

کد سی تابع مورد نظر

extern "C"
{
JNIEXPORT jstring JNICALL Java_com_myhouse_HappyJavaClass_awesomeCppFunction(JNIEnv* env, jobject thiz, jint myIntParam, jstring myStringParam);
};

JNIEXPORT jstring JNICALL Java_com_myhouse_HappyJavaClass_awesomeCppFunction(JNIEnv* env, jobject thiz, jint myIntParam, jstring myStringParam)
{
    // your C++ code goes here
}

برای ارسال مقادیر متفاوت و بازگردانی مقادیر نیز می توانید به نمونه کد های که در زیر آمده است مراجعه کنید .

برای استفاده از انواع داده ساده مثل jint , jchar , jbool از مشاهبه آنها در سی استفاده می شود .

JNIEXPORT void JNICALL Java_com_myhouse_HappyJavaClass_awesomeCppFunction(JNIEnv* env, jobject thiz, jint myIntParam)
{
    int myCppVariable = myIntParam;
}

برای سایر داده ها مثل اشیاء خاص باید آنها را به نوع معادل سی تبدیل  کرد به عنوان مثال برای رشته به صورت زیر عمل می شود .

JNIEXPORT void JNICALL Java_com_myhouse_HappyJavaClass_awesomeCppFunction(JNIEnv* env, jobject thiz, jstring myStringParam)
{
      const char* str = env->GetStringUTFChars(myStringParam, NULL);

      // use the value

      env->ReleaseStringUTFChars(myStringParam, str);
}

ارایه ای از اعداد صحیح :ارایه ای از اعداد صحیح :

JNIEXPORT void JNICALL Java_Simple_passArray(JNIEnv *env, jobject obj, jintArray ptr)
{
    int i;

    jsize len = env->GetArrayLength(env, ptr);
    jint *body = env->GetIntArrayElements(env, ptr, 0);

    for (i=0; i < len; i++)
        printf("Hello from JNI - element: %d\n", body[i]);

    env->ReleaseIntArrayElements(env, ptr, body, 0);
}

ارایه ای از رشته ها:ارایه ای از رشته ها:

JNIEXPORT void JNICALL Java_Simple_passArray(JNIEnv *env, jobject obj, jstringArray ptr)
{
    int i;

    jsize len = env->GetArrayLength(env, ptr);
    jstring *body = env->GetObjectArrayElement(env, ptr, 0);

    for (i=0; i < len; i++)
    {
        const char *rawString = env->GetStringUTFChars(body[i], false);
        printf("Hello from JNI - element: %s\n", rawString);

        env->ReleaseStringUTFChars(body[i], rawString);
    }

    env->ReleaseObjectArrayElements(env, ptr, body, 0);
}

بازگشت مقادیر داده ساده به صورت زیر و با استفاده از همان نوع داد های سی صورت می پذیرد 

JNIEXPORT jint JNICALL Java_com_myhouse_HappyJavaClass_awesomeCppFunction(JNIEnv* env, jobject thiz)
{
    int i = 3;

    return i;
}

برای برگرداندن اشیاء باید به معادل jni تبدیل شوند .

JNIEXPORT jstring JNICALL Java_com_myhouse_HappyJavaClass_awesomeCppFunction(JNIEnv* env, jobject thiz)
{
    jstring result = env->NewStringUTF(FacebookManager::GetInstance()->GetWhitelistDevIds());
    env->DeleteLocalRef(result);
    return result;
}

برگرداندن ارایه ای از اعداد صحیح:

JNIEXPORT jintArray JNICALL Java_com_myhouse_HappyJavaClass_awesomeCppFunction(JNIEnv* env, jobject thiz)
{
    jintArray result;
    result = env->NewIntArray(env, size);
    if (result == NULL) {
        return NULL; /* out of memory error thrown */
    }

    int i;
    // fill a temp structure to use to populate the java int array
    jint fill[256];
    for (i = 0; i < size; i++) {
        fill[i] = 0; // put whatever logic you want to populate the values here.
    }
    // move from the temp structure to the java structure
    env->SetIntArrayRegion(env, result, 0, size, fill);
    return result;
}

بازگردانی ارایه ای از رشته ها :

JNIEXPORT jobjectArray JNICALL Java_com_myhouse_HappyJavaClass_awesomeCppFunction(JNIEnv* env, jobject thiz)
{
    jobjectArray ret;  
    int i;  

    char *message[5]= {"first",   
                       "second",   
                       "third",   
                       "fourth",   
                       "fifth"};  

    ret= (jobjectArray)env->NewObjectArray(5,  
         env->FindClass("java/lang/String"),  
         env->NewStringUTF(""));  

    for(i=0;i<5;i++) {  
        env->SetObjectArrayElement(  
        ret,i,env->NewStringUTF(message[i]));  
    }  
    return(ret);  
}

منبع 

  • موافقین ۲ مخالفین ۰
  • پنجشنبه, ۲۹ مرداد ۱۳۹۴، ۱۱:۳۱ ب.ظ
به اشتراک می گذارم : به اشتراک بگذاریم به اشتراک بگذاریم به اشتراک بگذاریم به اشتراک بگذاریم

نظرات  (۱)

سلام
لینک ها رو برسی کن بعد قرار بده (کد نمونه)
پاسخ:
من نیازی به نمونه کدا پیدا نکردم.لینکا مثل اینکه مشکل داشت کلا حذفش کردم ممنون