顯示具有 jni 標籤的文章。 顯示所有文章
顯示具有 jni 標籤的文章。 顯示所有文章

[cocos2d-x / Android篇]教學4︰在Eclipse專案裡使用EasyNDK

文章撰寫日期︰2013/12/29 20:04
cocos2d-x使用版本︰2.1.4

一、前言

接下來的教學跟前三篇昔昔相關,
建議先理解ios端使用EasyNDK的方式,
將更好入手本篇和後面的教學。

二、文章開始

繼EasyNDK第2篇的教學,
我們在C++的Classes\HelloWorldScene.cpp關閉按鈕的函式裡寫了SendMessageWithParams呼叫Objective-C(Native)端的 函式SampleSelector 後,
現在要用一樣的方式呼叫在Android端Activity(Native)裡的 函式SampleSelector了。

第1步 匯入TestEasyNDK專案檔進Eclipse

按下確定匯入專案。

第2步 複製EasyNDK相關資源至Eclipse專案中

我們需將EasyNDK 套件檔(Cpp檔)、Android.mk(C++編譯成Android APK的範本檔)、和EasyNDK.java、EasyNDK在Android端相關的java檔 複製進Eclipse專案目錄TestEasyNDK底下
EasyNDK套件檔(cpp檔)
Android編譯C++使用的範本檔(Android.mk)
EasyNDK在Android端相關的java檔
然後再將EasyNDK.java取代建置專案時的TestEasyNDK.java,
並將AndroidManifest.xml裡的內容修改如下

第3步 重新清除並編譯專案

重新清除TestEasyNDK專案,確保C++檔重新被NDK編譯

成功了!

NDK編譯成功後,
按下右下角的關閉按鈕,
成功岀現了從C++傳來的訊息。

三、其它

附上該教學文相關資源

專案目錄最後的結構
源始碼下載

相關文章

1. 在ios端使用EasyNDK
2. 官方教學

[cocos2d-x / ios篇]教學2︰使用EasyNDK從C++呼叫Objective-C

文章撰寫日期︰2013/12/29 16:40
cocos2d-x使用版本︰2.1.4

一、前言

繼上一篇我們在Xcode專案初始化EasyNDK環境後,
這篇就要繼續來說明怎麼從C++呼叫Objective-C

二、文章開始

底下示例從 C++ 叫岀 IOS 的 UIAlertView彈跳視窗。

實作C++端

在Classes\HelloWorldScene.cpp開始處宣告
#include "NDKHelper.h"

然後修改關閉按鈕觸發後的事件如下
void HelloWorld::menuCloseCallback(CCObject* pSender)
{
    CCLog(__FUNCTION__);
    
    // 在C++中呼叫Objective-C的函式︰SampleSelector
    SendMessageWithParams(string("SampleSelector"), NULL);
}

實作Objective-C端

在ios\RootViewController.h宣告即將從C++呼叫的函式SampleSelector

在RootViewController.mm裡匯入EasyNDK套件
#include "IOSNDKHelper.h"

添加底下函式讓Objective-C端註冊IOSNDKHelper,
目的是讓RootViewController.mm有能力監聽從C++端傳來的呼叫
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {

        // 告訴NDKHelper說 RootViewController會回應來自C++的message
        [IOSNDKHelper SetNDKReciever:self];
        
    }
    return self;
}

實作SampleSelector函式
- (void) SampleSelector:(NSObject *)prms
{
    NSLog(@"Objective-C端的SampleSelector被呼叫了");
    
    // Show a bogus pop up here
    UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"Hello World!"
                                                      message:@"This is a sample popup on iOS"
                                                     delegate:nil
                                            cancelButtonTitle:@"OK"
                                            otherButtonTitles:nil];
    [message show];
}

成功了!

執行專案,
此時看到ios simulator跳岀畫面如下
從C++呼叫岀來的UIAlertView彈跳視窗

三、結論

從上面的教學來看,
從C++呼叫Objective-C一點也不難。
只要將EasyNDK專案匯入遊戲專案,
然後在.cpp和.mm檔引用套件並使用EasyNDK的函式SendMessageWithParams,
便能輕易地與Objecitve-C溝通。

這篇教學文的目的是簡單易懂,
如果您還有進階的需求,
像是想用SendMessageWithParams傳送Object給Objective-C,
或者希望從Objective-C呼叫回C++端,
可以參考官方教學使用CCDictionary的方式或者下一篇。

[Android-JNI篇]Fatal signal 11,找不到JNI函式

文章撰寫日期︰2013/07/17 11:42
cocos2dx使用版本︰v 2.0.4
cocosBuilder使用版本︰v 2.0 alpha 1

一、問題

今天在寫JNI試圖從C++ call JAVA時,
遇到了
Fatal signal 11 (SIGSEGV) xxxx
的問題,
告訴我找不到JAVA層的某個static函式。


二、解決辦法

JAVA端的Code如下
package com.simon.utility;
public class DataManager {
 public static void test(){
  
  Log.i("tag", "into test");
 }
}
 
C++端使用JNI呼叫上面的Java函式
void FileOperator::getAndroidTest(){
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
    CCLog("into FileOperator::getAndroidTest(), Involking JNI...");
    
    JniMethodInfo t;
    
    if (JniHelper::getStaticMethodInfo(t, "com/simon/utility/DataManager","test","()V;"))
    {
        CCLog("classID: %d",t.classID);
                CCLog("methodID: %d",t.methodID);
        t.env->CallStaticBooleanMethod(t.classID,t.methodID);
        
    }
#endif
}
 
程式一直跟我報找不到test這個函式,
後來才知道()V;那邊
V後面不用打分號!

題外話︰
()是JAVA端接收參數的值
V是這隻JAVA函式是否有回傳值。

[Android篇]call to OpenGL ES API with no current context (logged once per thread)

文章撰寫日期︰2013/04/16 13:25
cocos2dx使用版本︰v 2.0.4
cocosBuilder使用版本︰v 2.0 alpha 1

一、問題

今天試圖使用JNI從Java(Android)層呼叫C++(Cocos2d-x)層,
讓Cocos2d-x換場景(replaceScene),
卻遇到Eclipse報
  1. Fatal signal 11 (SIGSEGV) at xxxxxxxx (code=1), thread xxxx (xxxxxx)
  2. call to OpenGL ES API with no current context (logged once per thread)
的錯誤。

二、解決辦法

這個問題是因為Android在啟動cocos2d-x的Thread時,
不是用context的主Thread,
而是另外產生OpenGL的Thread,
所以我們不能用主Thread去讓cocos2dx做OpenGL Thread原本應該做的工作(replaceScene),
要用OpenGL的Thread去完成︰

JAVA端-Cocos2dxActivity.java
//要用Cocos2dxActivty這個Activity去調用runOnGLThread!
Cocos2dxActivity.this.runOnGLThread(new Runnable(){

    @Override
    public void run() {
           replaceScene();
        }
    });

    public static native void replaceScene();
    static {
        System.loadLibrary("game");
   }

C++端
JNIEXPORT void JNICALL Java_com_hardworking_millioinschool_ios_Cocos2dxActivity_replaceScene(JNIEnv *env, jobject thiz)
{
    
    //切到主遊戲頁
    CCScene *pScene = TitleScene::scene();
    CCDirector::sharedDirector()->replaceScene(pScene);
    
}

相關文章

1. 雜物聚集地