android基礎(chǔ)鞏固之ndk

環(huán)境配置

為了工程不出現(xiàn)問題最好是新建項(xiàng)目的時(shí)候選擇c++/c項(xiàng)目支持 (android studio創(chuàng)建項(xiàng)目)

app/library module gradle 配置

apply plugin: 'com.android.library'

android {
    defaultConfig {
       externalNativeBuild {
           cmake {
               cppFlags ""
           }
       }

       ndk {
           ldLibs "log"http://實(shí)現(xiàn)__android_log_print
           abiFilters  'x86', 'armeabi-v7a'
       }

    }

    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
        }
    }

}

src/main/cpp/CMakeList.txt 項(xiàng)目創(chuàng)建的時(shí)候會(huì)自動(dòng)生成畜晰,如果沒有從其它地方復(fù)制 , main/cpp目錄不存在就自己創(chuàng)建

cmake_minimum_required(VERSION 3.4.1)

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             native-lib.cpp
        )

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )


target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

native-lib.cpp 選擇cpp是因?yàn)榱私膺@塊,各選語言###

#include <jni.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <android/log.h>

using namespace std;

#define  LOG_TAG    "zzg-ndk"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGD(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_example_zyframework_SDKApi_isExpired(JNIEnv *env, jobject jobj, jlong time) {

    LOGE("native isExpret time = %lld ", time);
    return (jboolean) b;
}

使用示例

1.數(shù)據(jù)傳遞

  • java傳遞數(shù)據(jù)給c(包含對(duì)象)
  • c傳遞數(shù)據(jù)給java(包含對(duì)象)

java傳遞數(shù)據(jù)給c,c返回?cái)?shù)據(jù)給java(包含對(duì)象)

java代碼

static {
    System.loadLibrary("native-lib");
}

private String    tag = "zzg-ndk";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Example of a call to a native method
    TextView tv = findViewById(R.id.sample_text);
    tv.setText(stringFromJNI());

    SimpleDateFormat simpleDateFormat = new SimpleDateFormat
            ("yyyy-MM-dd HH:mm:ss");
    String dateStr = simpleDateFormat.format(new Date());
    sayHello(dateStr);

    int addV = add(12, 5);
    Log.e(tag, "c add result = " + addV);

    float f = getFloat(3.1415926f);
    Log.e(tag, "c getFloat result = " + f);

    double d = getDouble(35.0);
    Log.e(tag, "c getDouble result = " + d);

    boolean b = getBoolean(true);
    Log.e(tag, "c getBoolean result = " + b);

    String s = getString("打開電視");
    Log.e(tag, "c getString result = " + s);

    long l = getLong(3500l);
    Log.e(tag, "c getDouble result = " + l);

    String[] n_arr = getStringArray(new String[]{"上海", "天津", "濟(jì)南"});
    for (String s_t : n_arr) {
        Log.e(tag, s_t);
    }

    /**
     * 在c層進(jìn)行對(duì)象的轉(zhuǎn)換
     */
    ResultInfo resultInfo = new ResultInfo("2018-12-22", 39);
    Log.e(tag, "resultInfo = " + resultInfo);
    WeatherInfo weatherInfo = convertInfo(resultInfo);
    if (weatherInfo != null) {
        Log.e(tag, "weatherInfo = " + weatherInfo);
    }
}

public native String stringFromJNI();
private native void sayHello(String str);
private native int add(int a, int b);
private native float getFloat(float f);
private native double getDouble(double d);

private native boolean getBoolean(boolean b);
private native String getString(String str);
private native long getLong(long l);
private native String[] getStringArray(String[] sa);
/**
 * 對(duì)象轉(zhuǎn)換
 */
private native WeatherInfo convertInfo(ResultInfo info);

cpp代碼

#include <jni.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <android/log.h>

using namespace std;

#define  LOG_TAG    "zzg-ndk"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGD(...)  __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

extern "C" JNIEXPORT jstring JNICALL
Java_com_example_hncpp_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    jstring sr = env->NewStringUTF(hello.c_str());
    const char *locstr = env->GetStringUTFChars(sr, 0);
    LOGE("stringFromJNI locstr = %s", locstr);
    env->ReleaseStringUTFChars(sr, locstr);
    return sr;
}

extern "C"
JNIEXPORT void JNICALL
Java_com_example_hncpp_MainActivity_sayHello(JNIEnv *env, jobject obj, jstring str_) {
    const char *str = env->GetStringUTFChars(str_, 0);
    env->ReleaseStringUTFChars(str_, str);
    LOGE("sayHello str = %s", str);
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_example_hncpp_MainActivity_add(JNIEnv *env, jobject obj, jint a, jint b) {
    int i = a;
    int j = b;
    LOGE("add 接收到的java 數(shù)據(jù):a =  %d , b =  %d", a, b);
    LOGE("add 轉(zhuǎn)換之后c的數(shù)據(jù):i = %d , j = %d", i, j);
    return i + j;
}

extern "C"
JNIEXPORT jfloat JNICALL
Java_com_example_hncpp_MainActivity_getFloat(JNIEnv *env, jobject obj, jfloat f) {
    float f_l = f;
    LOGE("getFloat 接收到的java 數(shù)據(jù):f = %3f ", f);
    LOGE("getFloat 轉(zhuǎn)換之后c的數(shù)據(jù):f_l = %3f", f_l);
    f_l = f_l * 0.2f;
    LOGE("getFloat 計(jì)算之后的數(shù)據(jù):f_l = %3f", f_l);
    return (jfloat) f_l;
}

extern "C"
JNIEXPORT jdouble JNICALL
Java_com_example_hncpp_MainActivity_getDouble(JNIEnv *env, jobject obj, jdouble d) {
    double d_1 = d;
    LOGE("getDouble 接收到的java 數(shù)據(jù):d = %1f ", d);
    LOGE("getDouble 轉(zhuǎn)換之后c的數(shù)據(jù):d_l = %1f", d_1);
    d_1 = 3 * d_1;
    LOGE("getFloat 計(jì)算之后的數(shù)據(jù):d_1 = %1f", d_1);
    return (jdouble) d_1;
}


extern "C"
JNIEXPORT jboolean JNICALL
Java_com_example_hncpp_MainActivity_getBoolean(JNIEnv *env, jobject obj, jboolean b) {
    unsigned char b_1 = b;
    LOGE("getDouble 接收到的java 數(shù)據(jù):d = %lu", b_1);
    if (b_1) {
        LOGE("true");
    } else {
        LOGE("false");
    }
    return !b_1;
}

//
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_hncpp_MainActivity_getString(JNIEnv *env, jobject obj, jstring str_) {
    const char *str = env->GetStringUTFChars(str_, 0);
//    LOGE("getDouble 接收到的java 數(shù)據(jù):str = %s", str);
//    std::string hello = "收到指令盈厘,準(zhǔn)備進(jìn)行操作, 操作成功";
//    env->ReleaseStringUTFChars(str_, str);
//    return env->NewStringUTF(hello.c_str());

//字符串拼接
//    string str = "Dream a Dream";
//    str.insert(str.length()," i have");
//    str.insert(0, " i have ");

//字符串拼接
    string tmp_s_1 = "收到指令 ", tmp_s_2 = " , 準(zhǔn)備進(jìn)行操作, 操作成功";
    tmp_s_1.insert(tmp_s_1.length(), str);
    tmp_s_1.insert(tmp_s_1.length(), tmp_s_2);
    env->ReleaseStringUTFChars(str_, str);
    return env->NewStringUTF(tmp_s_1.c_str());
}



extern "C"
JNIEXPORT jlong JNICALL
Java_com_example_hncpp_MainActivity_getLong(JNIEnv *env, jobject obj, jlong l) {
    long l_1 = l;
    LOGE("getDouble 接收到的java 數(shù)據(jù):l = %ld ", l);
    LOGE("getDouble 轉(zhuǎn)換之后c的數(shù)據(jù):l_1 = %ld", l_1);
    l_1 = 1.5f * l_1;
    LOGE("getFloat 計(jì)算之后的數(shù)據(jù):l_1 = %ld", l_1);
    return (jlong) l_1;
}

extern "C"
JNIEXPORT jobjectArray JNICALL
Java_com_example_hncpp_MainActivity_getStringArray(JNIEnv *env, jobject obj, jobjectArray sa) {
    int len = (*env).GetArrayLength(sa);
    int i = 0;
    // 獲取數(shù)據(jù)類型
    jclass objCls = env->FindClass("java/lang/String");
    // 生成新的數(shù)組
    jobjectArray jarr = (*env).NewObjectArray(len, objCls, 0);
    for (i = 0; i < len; i++) {
        jobject jobj = (*env).GetObjectArrayElement(sa, i);
        jstring str = static_cast<jstring>(jobj);
        const char *szStr = (*env).GetStringUTFChars(str, 0);
        LOGE("arr[%d] = %s ", i, szStr);
        env->ReleaseStringUTFChars(str, szStr);
//拼接數(shù)據(jù)
        string t_new = "new_";
        t_new.insert(t_new.length(), szStr);
        env->SetObjectArrayElement(jarr, i, env->NewStringUTF(t_new.c_str()));
    }
    return jarr;
}

//對(duì)象轉(zhuǎn)換
extern "C"
JNIEXPORT jobject JNICALL
Java_com_example_hncpp_MainActivity_convertInfo(JNIEnv *env, jobject jobj, jobject rInfo) {
    // 獲取傳入的對(duì)象的值
    jclass r_info_jcls = (*env).GetObjectClass(rInfo);
    // 這里通過反射的方式取字段的值
    jfieldID r_info_date_jfid = (*env).GetFieldID(r_info_jcls, "date", "Ljava/lang/String;");
    // 取date值
    jobject r_info_date_jobj = (*env).GetObjectField(rInfo, r_info_date_jfid);
    // 這里是java字符串
    jstring r_info_date_jstr = static_cast<jstring>(r_info_date_jobj);
    const char *r_info_date_cstr = (*env).GetStringUTFChars(r_info_date_jstr, 0);
    // 釋放資源
    (*env).ReleaseStringUTFChars(r_info_date_jstr, r_info_date_cstr);
    LOGE("ndk ->ndk -> date = %s", r_info_date_cstr);

    // 這里通過調(diào)用方法取到tmp值
    jmethodID jmid_rinfo_get_tmp = (*env).GetMethodID(r_info_jcls, "getTmp", "()I");
    jint val_rinfo_tmp = (*env).CallIntMethod(rInfo, jmid_rinfo_get_tmp);
    LOGE("ndk ->ndk -> val_rinfo_tmp = %d", val_rinfo_tmp);


    // 在c層中構(gòu)建WeatherInfo對(duì)象敷鸦,設(shè)置數(shù)據(jù),可以通過調(diào)用方法也可以通過設(shè)置成員變量來實(shí)現(xiàn)
    jclass w_info_jcls = (*env).FindClass("com/example/hncpp/WeatherInfo");
    // 找到構(gòu)造方法id,無參構(gòu)造
    jmethodID jmid_const_w_info = (*env).GetMethodID(w_info_jcls, "<init>", "()V");
    // 構(gòu)建java對(duì)象
    jobject jobj_w_info = (*env).NewObject(w_info_jcls, jmid_const_w_info);
    // 設(shè)置屬性可以通過調(diào)用GetFieldID->SetFileID來設(shè)置脆炎,也可以通過GetMethodId->CallMethodId,總之,哪個(gè)方便用哪個(gè)
    // 我們這里用簡(jiǎn)單的操作
    jmethodID jmid_winfo_setid = (*env).GetMethodID(w_info_jcls, "set_id", "(I)V");
    (*env).CallVoidMethod(jobj_w_info, jmid_winfo_setid, 35);

    jmethodID jmid_winfo_setdate = (*env).GetMethodID(w_info_jcls, "setDate",
                                                      "(Ljava/lang/String;)V");
    (*env).CallVoidMethod(jobj_w_info, jmid_winfo_setdate, r_info_date_jstr);

    jmethodID jmid_winfo_settmp = (*env).GetMethodID(w_info_jcls, "setTmp", "(I)V");
    (*env).CallVoidMethod(jobj_w_info, jmid_winfo_settmp, val_rinfo_tmp);
    return jobj_w_info;
}

2.c調(diào)用java成員變量\方法\創(chuàng)建java層對(duì)象

Utils類代碼

public class Utils {
    public static String TEST_LOG_TAG = "zzg_log";
    private static String TEST_LOG_TAG2 = "zzg_log_2";
    private static int build_num = 35;
    public String app_old_version = "v0.0.3";
    public long person_id = 430644198806230032l;
    private String app_version = "v1.3.0";
    private int test_num = 50;
    private long phone_num = 13244105539l;

    private Utils() {
        Log.e(TEST_LOG_TAG, "私有構(gòu)造觸發(fā)了");
    }

    public Utils(int t) {
        Log.e(TEST_LOG_TAG, "公有構(gòu)造觸發(fā)了,param = " + t);
    }

    public static void logE(String str) {
        Log.e(TEST_LOG_TAG, str);
    }

    public static void logE(String logTag, String str) {
        Log.e(logTag, str);
    }

    private static long getAppRunTimer() {
        return 3500l;
    }

    private boolean isAppRunning() {
        return true;
    }

    public native void test();
}

java方法

cpp代碼

公有靜態(tài)成員變量調(diào)用

//公開的靜態(tài)方法和成員變量
jclass jcls = env->GetObjectClass(jobj);

//調(diào)用java的靜態(tài)成員變量
jfieldID jfid = (*env).GetStaticFieldID(jcls, "TEST_LOG_TAG", "Ljava/lang/String;");
jstring jlog_tag = static_cast<jstring>((*env).GetStaticObjectField(jcls, jfid));
const char *jlogtag_str = (*env).GetStringUTFChars(jlog_tag, 0);
(*env).ReleaseStringUTFChars(jlog_tag, jlogtag_str);
LOGE("獲取到的屬性 log_tag value = %s", jlogtag_str);

調(diào)用私有java的靜態(tài)成員變量

jfieldID log2_jfid = (*env).GetStaticFieldID(jcls, "TEST_LOG_TAG2", "Ljava/lang/String;");
jstring jlog2_tag = static_cast<jstring>((*env).GetStaticObjectField(jcls, log2_jfid));
const char *jlog2tag_str = (*env).GetStringUTFChars(jlog2_tag, 0);
(*env).ReleaseStringUTFChars(jlog2_tag, jlog2tag_str);
LOGE("獲取到的屬性 log_tag jlog2_tag = %s", jlog2tag_str);

調(diào)用java的公有靜態(tài)方法

jmethodID loge_m = (*env).GetStaticMethodID(jcls, "logE", "(Ljava/lang/String;)V");
jstring log_c = (*env).NewStringUTF("從c調(diào)用的方法,請(qǐng)刷新界面");
(*env).CallStaticVoidMethod(jcls, loge_m,log_c);

調(diào)用java的公有非靜態(tài)成員變量

jfieldID jfid = (*env).GetFieldID(jcls, "app_old_version", "Ljava/lang/String;");
jstring jlog_tag = static_cast<jstring>((*env).GetObjectField(jobj, jfid));
const char *jlogtag_str = (*env).GetStringUTFChars(jlog_tag, 0);
(*env).ReleaseStringUTFChars(jlog_tag, jlogtag_str);
LOGE("獲取到的屬性 log_tag value = %s", jlogtag_str);

調(diào)用私有非靜態(tài)的成員變量

//    GetFieldID默認(rèn)獲取的就是私有的
jfieldID jfid = (*env).GetFieldID(jcls, "test_num", "I");
jint test_n = (*env).GetIntField(jobj, jfid);
LOGE("獲取到的屬性 test_num value = %d", test_n);

調(diào)用私有非靜態(tài)的成員String變量

jfieldID app_vers_fid = (*env).GetFieldID(jcls, "app_version", "Ljava/lang/String;");
// 這里容易傳錯(cuò)GetObjectField(jobj, app_vers_fid)可千萬要注意
jobject app_vers_obj = (*env).GetObjectField(jobj, app_vers_fid);
jstring app_ver_str = static_cast<jstring>(app_vers_obj);
if (app_ver_str != NULL) {
    const char *app_ver_cstr = (*env).GetStringUTFChars(app_ver_str, 0);
    (*env).ReleaseStringUTFChars(app_ver_str, app_ver_cstr);
    LOGE("獲取到的屬性 log_tag app_version = %s", app_ver_cstr);
}

調(diào)用公私有非靜態(tài)的成員long變量

person_id公有

jfieldID person_id_fid = (*env).GetFieldID(jcls, "person_id", "J");
// 這里容易傳錯(cuò)GetObjectField(jobj, app_vers_fid)可千萬要注意
jlong person_id = (*env).GetLongField(jobj, person_id_fid);
LOGE("獲取到的屬性 log_tag person_id = %lld", person_id);

phone_num私有

jfieldID phone_num_fid = (*env).GetFieldID(jcls, "phone_num", "J");
// 這里容易傳錯(cuò)GetObjectField(jobj, app_vers_fid)可千萬要注意
jlong phone_num = (*env).GetLongField(jobj, phone_num_fid);
LOGE("獲取到的屬性 log_tag phone_num = %lld", phone_num);

3. static native 使用示例

3. static native 靜態(tài)的native方法

c代碼中調(diào)用java中的方法示例

java代碼

public class SDKUtils {
    public void setTag(String tag) {
        Log.e("zzg-ndk", "setTag tag = " + tag);
    }

    public static native void updateTag(String key);
}
cpp代碼
extern "C"
JNIEXPORT void JNICALL
Java_com_example_sdkjiagu_SDKUtils_updateTag(JNIEnv *env, jclass jcls, jstring key_) {
    const char *key = env->GetStringUTFChars(key_, 0);
    LOGE("native updateTag key = %s ", key);
    env->ReleaseStringUTFChars(key_, key);
    // 得到j(luò)object不會(huì)走構(gòu)造方法
    jobject jobj = (*env).AllocObject(jcls);
    jmethodID _mid = (*env).GetMethodID(jcls, "setTag", "(Ljava/lang/String;)V");

    string t_new = "2019-01-18 23:59:59";
    (*env).CallVoidMethod(jobj,_mid,env->NewStringUTF(t_new.c_str()));
}

輔助資料

ndk編譯之后so的路徑

\HelloNdkCpp\ZYFramework\build\intermediates\cmake\debug\obj\x86

方法的方法簽名的查看

as 3.1.2

app/build/intermediates/classes/debug/com/example/hncpp

as 3.3.0

cmd -> javap -s Utils

public class com.example.hncpp.Utils {
  public java.lang.String app_old_version;
    descriptor: Ljava/lang/String;
  public static java.lang.String TEST_LOG_TAG;
    descriptor: Ljava/lang/String;
  public com.example.hncpp.Utils(int);
    descriptor: (I)V

  public static void logE(java.lang.String);
    descriptor: (Ljava/lang/String;)V

  public static void logE(java.lang.String, java.lang.String);
    descriptor: (Ljava/lang/String;Ljava/lang/String;)V

  public native void test();
    descriptor: ()V

  static {};
    descriptor: ()V
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末筝尾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌件豌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件控嗜,死亡現(xiàn)場(chǎng)離奇詭異茧彤,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)疆栏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門曾掂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人壁顶,你說我怎么就攤上這事珠洗。” “怎么了若专?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵许蓖,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我调衰,道長(zhǎng)膊爪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任嚎莉,我火速辦了婚禮米酬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘趋箩。我一直安慰自己赃额,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布叫确。 她就那樣靜靜地躺著爬早,像睡著了一般。 火紅的嫁衣襯著肌膚如雪启妹。 梳的紋絲不亂的頭發(fā)上筛严,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音饶米,去河邊找鬼桨啃。 笑死,一個(gè)胖子當(dāng)著我的面吹牛檬输,可吹牛的內(nèi)容都是我干的照瘾。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼丧慈,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼析命!你這毒婦竟也來了主卫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤鹃愤,失蹤者是張志新(化名)和其女友劉穎簇搅,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體软吐,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瘩将,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了凹耙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片姿现。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖肖抱,靈堂內(nèi)的尸體忽然破棺而出备典,到底是詐尸還是另有隱情,我是刑警寧澤意述,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布提佣,位于F島的核電站,受9級(jí)特大地震影響欲险,放射性物質(zhì)發(fā)生泄漏镐依。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一天试、第九天 我趴在偏房一處隱蔽的房頂上張望槐壳。 院中可真熱鬧,春花似錦喜每、人聲如沸务唐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枫笛。三九已至,卻和暖如春刚照,著一層夾襖步出監(jiān)牢的瞬間刑巧,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工无畔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留啊楚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓浑彰,卻偏偏與公主長(zhǎng)得像恭理,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子郭变,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355