Rodhos Soft

備忘録を兼ねた技術的なメモです。Rofhos SoftではiOSアプリ開発を中心としてAndroid, Webサービス等の開発を承っております。まずはご相談下さい。

iframeとタイマー

タイマーでiframeを切り替えてみた。

function getID(identifier:string):string {
    return '[data-id="' + identifier +'"]'
}

const x:JQuery<HTMLIFrameElement> = $(getID("child")) as JQuery<HTMLIFrameElement>

const y = x.get(0);

setTimeout(function(){
    y.src ="./hoge.html";
},2000)

y.src = "./hogehoge.html";

文字列受け渡し

class Hello {
    companion object {
        init {
            System.loadLibrary("Hello")
        }
    }

    external fun printHello()
    external fun printNative(str:String, len:Int);
}

fun main(args: Array<String>) {
    Hello().printHello()
    val str = "hello form kotoln"
    Hello().printNative(str, str.length)
}

でcpp側は

#include "Hello.h"
#include <iostream>
#include <string>
extern "C" {
    JNIEXPORT void JNICALL Java_Hello_printHello
    (JNIEnv *env, jclass obj) {
        std::cout << "hello cpp" << std::endl;
    }
    
    JNIEXPORT void JNICALL Java_Hello_printNative
    (JNIEnv *env, jclass obj, jstring str, jint len) {
        /// charに変換
        jboolean iscopy;
        const char* msgStr = env->GetStringUTFChars(str, &iscopy);
        char* copiedChars = strdup(msgStr);
        env->ReleaseStringUTFChars(str, msgStr);
        env->DeleteLocalRef(str);

        printf("%s\n", copiedChars);
    }
}

でいけた。 が、おそらくこの辺の文字コードの話がいるはず…。

Java とか Android (DEX) の MUTF-8 (Modified UTF-8) って何者よ?っていう話 - bearmini's blog

とか

  java, a unicode char will be encoded with 4 bytes (utf16).
  jstring will container characters  utf16
  std::string in c++ is essentially a string of bytes, not characters,not characters
 we have convert utf16 to bytes.

とか

  • 返却値
class Hello {
    companion object {
        init {
            System.loadLibrary("Hello")
        }
    }

    external fun printHello()
    external fun printNative(str:String, len:Int): Boolean;
}

fun main(args: Array<String>) {
    Hello().printHello()
    val str = "hello form kotoln"
    val ret = Hello().printNative(str, str.length)
    println("ret = " + ret)
}
#include "Hello.h"
#include <iostream>
#include <string>
extern "C" {
    JNIEXPORT void JNICALL Java_Hello_printHello
    (JNIEnv *env, jclass obj) {
        std::cout << "hello cpp" << std::endl;
    }
    
    JNIEXPORT jboolean JNICALL Java_Hello_printNative
    (JNIEnv *env, jclass obj, jstring str, jint len) {
        /// charに変換
        jboolean iscopy;
        const char* msgStr = env->GetStringUTFChars(str, &iscopy);
        char* copiedChars = strdup(msgStr);
        env->ReleaseStringUTFChars(str, msgStr);
        env->DeleteLocalRef(str);

        printf("%s\n", copiedChars);
        
        return true;
    }
}

kotlinでhelloworld

class Hello {
    companion object {
        init {
            System.loadLibrary("Hello")
        }
    }

    external fun printHello()
}

fun main(args: Array<String>) {
    Hello().printHello()
}

コンパイル

kotlinc hello.kt

前回同様ライブラリを用意して実行

kotlin HelloKt

cppでhelloworld

cのときと同様でhello.cppを作る。

#include "Hello.h"
#include <iostream>
extern "C" {
    JNIEXPORT void JNICALL Java_Hello_printHello
    (JNIEnv *env, jclass obj) {
        std::cout << "hello cpp" << std::endl;
    }
}

あとはコンパイル時に-libc++をつける。

 gcc -shared -I/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/include -I/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/include/darwin Hello.cpp -o libHello.dylib -lstdc++

他は同じ

cでhelloworld

java側を用意

public class Hello {
    static{
        System.out.println(java.library.path);

        System.loadLibrary("Hello");
    }
    
    static native void printHello();

    public static void main(String args[]){
        printHello();
    }
}

コンパイル

javac Hello.java

C側を作成、ヘッダ作成

javah Hello
#include <jni.h>
/* Header for class Hello */

#ifndef _Included_Hello
#define _Included_Hello
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Hello
 * Method:    printHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_Hello_printHello
    (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif
#include "Hello.h"
#include <stdio.h>

JNIEXPORT void JNICALL Java_Hello_printHello
(JNIEnv *env, jclass obj) {
    printf("hello\n");
}

cをコンパイルするために含めるjniのヘッダーを入れるためjdkの場所を探す。

/usr/libexec/java_home -V

ライブラリ作成

gcc -shared -I/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/include -I/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home/include/darwin Hello.c -o libHello.dylib

使うライブラリを実行時に指定して実行

 java -Djava.library.path=. Hello

LD_LIBRARY_PATHに設定すると良い?

チュートリアル2

さらに簡単な例

#include <rxcpp/rx.hpp>


rxcpp::observable<std::string> twice(std::string word) {
    return rxcpp::observable<>::just(word + word);
}

rxcpp::observable<int> length(std::string word) {
    int l = (int)word.length();
    return rxcpp::observable<>::just(l);
}
rxcpp::observable<std::string> times(std::string word, int times) {
    auto r = word;
    for (int i=0;i<times;i++) {
        r = r + word;
    }
    return rxcpp::observable<>::just(r);
}

void useRxCpp() {
    auto ob = rxcpp::observable<>::just("poi")
    .flat_map([=](std::string word){
        return length(word);
    }).as_dynamic()
    .flat_map([=](int length){
        return times("hoge", length);
    }).as_dynamic()
    .flat_map([=](std::string word) {
        return twice(word);
    }).as_dynamic();
    
    ob.subscribe([=](std::string word) {
        std::cout << word << std::endl;
    });
}

チュートリアル

一番簡単な使い方

    
    rxcpp::observable<int> obs = rxcpp::observable<>::create<int>
    (
     [=](rxcpp::subscriber<int> s) {
         s.on_next(100);
         s.on_next(200);
         s.on_next(300);
         s.on_completed();
     }
     );
    
    
    auto x = obs.flat_map([=](int x) {
        return rxcpp::observable<>::just(x * 1000);
    }).as_dynamic()
    .flat_map([=](int x) {
        return rxcpp::observable<>::just("hoge");
    }).as_dynamic();
    
    auto l = x.subscribe([=](std::string txt){
        std::cout << txt << std::endl;
    });
    
    std::async(std::launch::async, [l]() {
        usleep(5*1000*1000);
        std::cout << "**unsubscribe**" << std::endl;
        l.unsubscribe();
    });

variant 共用体

かなり便利なことがわかった。

#include <boost/variant.hpp>
#include <iostream>

int main(int argc, const char * argv[]) {
    // insert code here...
    std::cout << "Hello, World!\n";
    
    boost::variant<int, std::string> v;
    v = 100;

    boost::variant<int, std::string> s;
    s = "200";

    if (v.type() == typeid(int)) {
        int l = boost::get<int>(v);
        std::cout << l + 1000 << std::endl;
        
        int* k = boost::get<int>(&v);
        std::cout << *k + 2000 << std::endl;
        
    }
    
    return 0;
}

boost設定

Macの場合。brewでinstall
/usr/local/Cellar/boost/1.67.0_1
ここにincludeヘッダーとlibがあるのでXCodeのパスを通す。
Header Search Pathsにinclude
Library Search Pathsにlib
non-recursive

Other linker flagに -lboost_system設定

チュートリアル的な記述7

typeerase的なものを作ってみたがポインタ周りが怪しいので修正中

#include "TypeErase.hpp"
#include <iostream>
#include <map>

class AnyBase;
using AnyBase_sp = std::shared_ptr<AnyBase>;

class AnyBase {
public:
    AnyBase() = default;
    virtual ~AnyBase() = default;
    
    template<typename T>
    T get();
  
    static AnyBase_sp make(std::string x);
    static AnyBase_sp make(int x);


};

template <typename T>
class Any;

template <typename T>
using Any_sp = std::shared_ptr<Any<T>>;



template <typename T>
class Any : public AnyBase {
public:
    Any(std::string x) : hold(x){};
    Any(int x): hold(x){};
    ~Any() {};
    T hold;
    static Any_sp<T> make(std::string x) {
        auto r = std::make_shared<Any<T>>(x);
        return r;
    }
};

template <typename T>
T AnyBase::get() {
    return dynamic_cast<Any<T>*>(this)->hold;
}

AnyBase_sp AnyBase::make(std::string x) {
    auto a = std::make_shared<Any<decltype(x)>>(x);
    return a;
}

AnyBase_sp AnyBase::make(int x) {
    auto a = std::make_shared<Any<decltype(x)>>(x);
    return a;
}




class Storage {
public:
    Storage() = default;
    ~Storage() = default;
    
};



void useTypeTrace() {

    AnyBase_sp xx = AnyBase::make("xxxxx");
    AnyBase_sp yy = AnyBase::make(33333);


    
//    std::cout << "typeErase " << x->get<int>() << std::endl;
    std::cout << "typeErase " << xx->get<std::string>() << std::endl;
    std::cout << "typeErase " << yy->get<int>() << std::endl;


}