ofxCef を使用した app を作る


ofxCef のビルド手順 の続きです。

環境

projectGenerator でプロジェクトを作成

いつもと同じように projectGenerator を使ってプロジェクトを生成します。
Addons で ofxCef にチェックを入れるのを忘れずに。

サーチパスの修正

僕の環境だとデフォルトのヘッダサーチパスが下記の様におかしなことになります。。

まずはこれを以下のように修正します。

  • $(OF_CORE_HEADERS)
  • ../../../addons/ofxCef-master/libs
  • ../../../addons/ofxCef-master/libs/CEF
  • ../../../addons/ofxCef-master/libs/CEF/osx32
  • ../../../addons/ofxCef-master/libs/CEF/osx32/include
  • ../../../addons/ofxCef-master/libs/CEF/osx32/include/base
  • ../../../addons/ofxCef-master/libs/CEF/osx32/include/base/internal
  • ../../../addons/ofxCef-master/libs/CEF/osx32/include/capi
  • ../../../addons/ofxCef-master/libs/CEF/osx32/include/internal
  • ../../../addons/ofxCef-master/libs/CEF/osx32/include/wrapper
  • ../../../addons/ofxCef-master/libs/CEF/osx32/lib
  • ../../../addons/ofxCef-master/src

ファイルタイプの変更

次に ofxCef の中で Objective-C のコードを使用しているファイルについて、そのファイルタイプを "Objective-C++ Source" に変更します。具体的には以下のファイルです。

  • ofxCEF.cpp
  • ofxCEFRenderHandler.cpp

process_helper_mac.cpp を削除

main関数が2つあるぞ!と怒られるので Build Phases > Compile Sources から process_helper_mac.cpp を削除します。

ライブラリを追加

General > Linked Frameworks and Libraries から以下を追加します。

  • Chromium Embedded Framework.framework
  • libcef_dll_wrapper.a

Chromium Embedded Framework.framework は $OF_PATH/addons/ofxCef-master/libs/CEF/osx32/lib に、libcef_dll_wrapper.a は前回ビルドしたものをそれぞれ使用します。

Run Script を追加

Build Phases > + > New Run Script Phase で以下のスクリプトを追加します。

exec cp -Rf "../../../addons/ofxCEF-master/libs/CEF/osx32/lib/Chromium Embedded Framework.framework" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/Contents/Frameworks/"
exit 1
exec install_name_tool -change "@executable_path/Chromium Embedded Framework" "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}"
exit 1
cp -Rf "../../../addons/ofxCef-master/example_ofxCEF/bin/cefHelper.app" "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/"
mv "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/cefHelper.app/Contents/MacOS/cefHelper" "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/cefHelper.app/Contents/MacOS/$PRODUCT_NAME Helper"
rm -rf "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/$PRODUCT_NAME Helper.app"
mv "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/cefHelper.app" "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/$PRODUCT_NAME Helper.app"
exec install_name_tool -change "@executable_path/Chromium Embedded Framework" "@executable_path/../../../../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/Frameworks/$PRODUCT_NAME Helper.app/Contents/MacOS/$PRODUCT_NAME Helper"
exec "../../../addons/ofxCef-master/example_ofxCEF/make_more_helpers.sh" Frameworks $PRODUCT_NAME

最後のスクリプトのみ Input Files に $(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_PATH)を追加してください。

ソースの修正

だいぶ疲れてきましたがもう少しです!

ofApp.h / .cpp を以下のように修正します。

ofApp.h
#pragma once

#include "ofMain.h"
#include "ofxCEF.h"

class GLFWwindow;

class ofApp : public ofBaseApp{

public:
        void setup();
        void update();
        void draw();
        void exit();

        // Chromium の JS からメッセージを受け取るためのハンドラ
        void gotMessageFromJS(ofxCEFMessageArgs& msg);
        // Chromium からイベント受け取るためのハンドラ
        void eventFromCEF(ofxCEFEventArgs& e);

        // CEF
        ofxCEF *cef;
};

ofApp.cpp
#include "ofApp.h"
#include "ofAppGLFWWindow.h"

// スクロールイベントを受け取るためのハンドラ
void mouseScroll(GLFWwindow* window, double x, double y){
    ((ofApp *)ofGetAppPtr())->cef->mouseWheel(x*10, y*10);
}

void ofApp::setup(){
#if defined(TARGET_OSX)
    // スクロールイベントのコールバックを登録
    glfwSetScrollCallback( ((ofAppGLFWWindow *) ofGetWindowPtr())->getGLFWWindow(), mouseScroll);
#endif

    cef->setup();

    ofAddListener(cef->messageFromJS, this, &ofApp::gotMessageFromJS);
    ofAddListener(cef->eventFromCEF, this, &ofApp::eventFromCEF);

    ofSetFrameRate(60);
    ofSetVerticalSync(true);

    cef->load("http://google.com");
}

void ofApp::update(){
    cef->update();
}

void ofApp::draw(){
    ofBackground(0);
    cef->draw();
}

void ofApp::exit() {
    cef->exit();
    delete cef;
    cef = NULL;
}

void ofApp::gotMessageFromJS(ofxCEFMessageArgs& msg){

}

void ofApp::eventFromCEF(ofxCEFEventArgs& e){

}

さらに main.cpp を以下のように修正します。

main.cpp
#include "ofMain.h"
#include "ofApp.h"
#include "ofAppGLFWWindow.h"

int main( ){

    // エントリーポイントでまず CEF を初期化
    int argc = 0;
    char** argv = NULL;
    ofxCEF * cef = initofxCEF(argc, argv);

    ofAppGLFWWindow window;
    ofSetupOpenGL(&window, 1400, 850, OF_WINDOW);

    // 初期化した CEF を ofApp に渡す
    ofApp * p = new ofApp();
    p->cef = cef;
    ofRunApp( p );
}

それではビルドしてみましょう。見慣れた Google のトップが表示されれば成功です!

まとめ

このようにまだまだ罠が多いですが、oF で Chromium の恩恵を受けられるのは大きいし、Web 系フロントエンドの人に UI を書いてもらってグラフィックスだけ oF で、という協働のしかたも考えられたりして夢が広がります。
今回は書きませんでしたが JS を使ったコミュニケーションも可能なので、今後も色々探っていきたいと思います。