国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Head First JNA

YPHP / 3224人閱讀

摘要:與動(dòng)態(tài)鏈接庫(kù)配套的,會(huì)有相應(yīng)的頭文件,來(lái)聲明動(dòng)態(tài)鏈接庫(kù)中對(duì)外暴露的方法。結(jié)構(gòu)體映射結(jié)構(gòu)體映射類編寫類,繼承,表示這個(gè)一個(gè)結(jié)構(gòu)體。聲明字段與,并且設(shè)置訪問(wèn)屬性為。計(jì)算機(jī)狀態(tài)結(jié)構(gòu)體結(jié)構(gòu)體指針結(jié)構(gòu)體具體的值至此,功能完成。

問(wèn)題描述

虛擬化項(xiàng)目,需要用到Java調(diào)用原生代碼的技術(shù),我們使用的是開源庫(kù)JNA(Java Native Access)。

Native(C/C++)代碼,編譯生成動(dòng)態(tài)鏈接庫(kù)Dynamic-link library

Windows下常見的.dll文件。這是我們項(xiàng)目中用到的動(dòng)態(tài)鏈接庫(kù)。

而在unix環(huán)境下,為.so文件。這是百度地圖的動(dòng)態(tài)鏈接庫(kù)。

與動(dòng)態(tài)鏈接庫(kù)配套的,會(huì)有相應(yīng)的頭文件,來(lái)聲明動(dòng)態(tài)鏈接庫(kù)中對(duì)外暴露的方法。

百度地圖是直接封裝好,給了.so,但是不給頭文件,直接把寫好的jar包給你,直接調(diào)用就行。

之前也是用過(guò)百度地圖的SDK,現(xiàn)在自己手寫代碼調(diào)用動(dòng)態(tài)鏈接庫(kù)才明白,原來(lái)之前用的都是別人封裝好的,如今自己參照頭文件手寫,感覺理解還是深刻了不少。

入門 待解決的問(wèn)題

我們使用JNA,主要是去調(diào)用動(dòng)態(tài)鏈接庫(kù)中已經(jīng)實(shí)現(xiàn)的方法,所以要解決的問(wèn)題就是:如何在Java代碼中調(diào)用動(dòng)態(tài)鏈接庫(kù)的方法?

打開頭文件,這個(gè)方法要求傳輸?shù)臄?shù)據(jù)是指針,而Java是沒有指針的,另一個(gè)問(wèn)題:Java數(shù)據(jù)類型與C/C++的數(shù)據(jù)類型如何映射?

方法映射

打開JNA的官方README,點(diǎn)擊Getting Started

直接看代碼,里面的sample,入門足夠了。

定義接口,繼承Library

定義該接口的一個(gè)實(shí)例,加載動(dòng)態(tài)鏈接庫(kù)。

在接口中聲明方法,該方法需要與原生代碼方法聲明一致。

然后該方法就映射到了原生的方法,我們只需調(diào)用該接口中的方法,即可調(diào)用到原生的對(duì)應(yīng)方法。

// This is the standard, stable way of mapping, which supports extensive
// customization and mapping of Java to native types.

public interface CLibrary extends Library {
    CLibrary INSTANCE = (CLibrary)
        Native.load((Platform.isWindows() ? "msvcrt" : "c"),
                            CLibrary.class);

    void printf(String format, Object... args);
}
類型映射 默認(rèn)類型映射

這是官方README中給的類型映射。

學(xué)習(xí)與實(shí)踐的區(qū)別,看著這個(gè)表格感覺挺簡(jiǎn)單的,實(shí)際用起來(lái)真難。

結(jié)構(gòu)體映射

結(jié)構(gòu)體PSA_HOST

typedef struct {
  char   name[33];
  DWORD  context;
} PSA_HOST;

映射類HostStruct

編寫類HostStruct,繼承Structure,表示這個(gè)一個(gè)結(jié)構(gòu)體。

聲明字段namecontext并且設(shè)置訪問(wèn)屬性為public

重寫getFieldOrder方法,表示本類中各字段以何順序映射原生結(jié)構(gòu)體。

/**
 * @author zhangxishuo on 2019-02-16
 * 結(jié)構(gòu)體 PSA_HOST
 */
public class HostStruct extends Structure {

    public byte[] name = new byte[33];

    public int context;

    @Override
    protected List getFieldOrder() {
        return Arrays.asList("name", "context");
    }
}

注意

const char *才能映射為String類型。

char *只能映射為byte數(shù)組,然后使用Native.toString()方法將byte數(shù)組轉(zhuǎn)換為String

方法映射
typedef PSA_STATUS (*LPFN_PSA_ShutdownHost)( PSA_LOGON_HANDLE *handle, IN PSA_HOST *psa_host );

參數(shù)中需要PSA_HOST結(jié)構(gòu)體的指針。

參考了好多篇文章,最常用的就是下面這種寫法。寫靜態(tài)內(nèi)部類,內(nèi)部類實(shí)現(xiàn)ByReferenceByValue接口,分別表示映射指針,與映射值。

/**
 * @author zhangxishuo on 2019-02-16
 * 結(jié)構(gòu)體 PSA_HOST
 */
public class HostStruct extends Structure {

    /**
     * 結(jié)構(gòu)體指針
     */
    public static class ByReference extends HostStruct implements Structure.ByReference {
    }

    /**
     * 結(jié)構(gòu)體具體的值
     */
    public static class ByValue extends HostStruct implements Structure.ByValue {
    }

    public byte[] name = new byte[33];

    public int context;

    @Override
    protected List getFieldOrder() {
        return Arrays.asList("name", "context");
    }
}

映射

/**
 * 關(guān)閉計(jì)算機(jī)
 * @param pointerByReference 認(rèn)證pointer
 * @param host               主機(jī)指針
 * @return 參見枚舉類PsaStatus
 */
NativeLong _PSA_ShutdownHost(PointerByReference pointerByReference,
                            HostStruct.ByReference host);
復(fù)雜類型

打起精神,重點(diǎn)來(lái)了!

開發(fā)過(guò)程中,有這樣一種復(fù)雜的數(shù)據(jù)結(jié)構(gòu),嵌套關(guān)系比較復(fù)雜。

typedef struct {
  union {
    DWORD flags;
    struct {
      DWORD rev:23;
      DWORD copy_status:3;
      DWORD timeout:1;
      DWORD disconnect:1;
      DWORD rev1:1;
      DWORD os_logoned:1;
      DWORD logoned:1;
      DWORD online:1;
    };
  };
} PSA_HOST_STATUS_FLAGS;

知識(shí)不用就忘,誰(shuí)還記得C語(yǔ)言里的聯(lián)合是啥?

Too young
struct {
  DWORD rev:23;
  DWORD copy_status:3;
  DWORD timeout:1;
  DWORD disconnect:1;
  DWORD rev1:1;
  DWORD os_logoned:1;
  DWORD logoned:1;
  DWORD online:1;
};

DWORD就是int,先映射里面的結(jié)構(gòu)體。

把這些屬性一寫,然后再重寫getFieldOrder方法。

/**
 * @author zhangxishuo on 2019-02-26
 * 計(jì)算機(jī)狀態(tài)結(jié)構(gòu)體
 */
public class HostStatusStruct extends Structure {

    /**
     * 結(jié)構(gòu)體指針
     */
    public static class ByReference extends HostStatusStruct implements Structure.ByReference {
    }

    /**
     * 結(jié)構(gòu)體具體的值
     */
    public static class ByValue extends HostStatusStruct implements Structure.ByValue {
    }

    public int rev;

    public int copy_status;

    public int timeout;

    public int disconnect;

    public int rev1;

    public int os_logoned;

    public int logoned;

    public int online;

    @Override
    protected List getFieldOrder() {
        return Arrays.asList("rev", "copy_status", "timeout", "disconnect", "rev1", "os_logoned", "logoned", "online");
    }
}
union {
  DWORD flags;
  struct {
    DWORD rev:23;
    DWORD copy_status:3;
    DWORD timeout:1;
    DWORD disconnect:1;
    DWORD rev1:1;
    DWORD os_logoned:1;
    DWORD logoned:1;
    DWORD online:1;
  };
};

然后再映射聯(lián)合,編寫一個(gè)類繼承Union,該類即映射到聯(lián)合。

/**
 * 聯(lián)合
 */
public static class UNION extends Union {
    public int flags;
    public HostStatusStruct hostStatusStruct;
}

最后映射最外層的PSA_HOST_STATUS_FLAGS

/**
 * @author zhangxishuo on 2019-02-26
 * 結(jié)構(gòu)體 PSA_HOST_STATUS_FLAGS
 */
public class HostStatusFlagsStruct extends Structure {

    /**
     * 聯(lián)合
     */
    public static class UNION extends Union {
        public int flags;
        public HostStatusStruct hostStatusStruct;
    }

    /**
     * 結(jié)構(gòu)體指針
     */
    public static class ByReference extends HostStatusFlagsStruct implements Structure.ByReference {
    }

    /**
     * 結(jié)構(gòu)體具體的值
     */
    public static class ByValue extends HostStatusFlagsStruct implements Structure.ByValue {
    }

    public UNION union;

    @Override
    protected List getFieldOrder() {
        return Collections.singletonList("union");
    }
}

看上去好像沒什么毛病,一切都這么簡(jiǎn)單嗎?當(dāng)然不是。

-1073741824

一調(diào)用,就炸了。

API文檔的聲明,flags應(yīng)該是沒什么具體含義的,而結(jié)構(gòu)體中應(yīng)該是我們想要獲取的信息。

那為什么flags有數(shù),而結(jié)構(gòu)體中卻沒有值呢?

聯(lián)合
struct TEST_STRUCT {
    int a,
    int b
};

union TEST_UNION {
    int a,
    int b
};

聲明映射類型

重寫read方法,當(dāng)讀取數(shù)據(jù)時(shí),設(shè)置聯(lián)合的類型為結(jié)構(gòu)體類型。

@Override
public void read() {
    super.read();
    union.setType(HostStatusStruct.class);
    union.read();
}
怪事

當(dāng)時(shí)這個(gè)問(wèn)題把我愁壞了,捯飭了一整天才學(xué)明白。

數(shù)字

一直是這個(gè)數(shù)字:-1073741824,這個(gè)數(shù)字是不是有什么問(wèn)題?

-1073741824轉(zhuǎn)換為32機(jī)的二進(jìn)制表示:

1100 0000 0000 0000 0000 0000 0000 0000

1073741824230次方。

問(wèn)題

問(wèn)題還是出在這個(gè)上:

struct {
  DWORD rev:23;
  DWORD copy_status:3;
  DWORD timeout:1;
  DWORD disconnect:1;
  DWORD rev1:1;
  DWORD os_logoned:1;
  DWORD logoned:1;
  DWORD online:1;
};

雖然DWORD就映射為int,但這里不是簡(jiǎn)單的映射:

rev:23表示rev32位。

copy_status:3表示copy_status3位。

timeout:1表示timeout1位。

內(nèi)存是倒著存的,所以數(shù)據(jù)應(yīng)該是這樣。

映射

原理知道了,那怎么映射呢?怎么映射一個(gè)一位的內(nèi)容呢?

StackOverflow上一老哥給出了解決方案,先寫個(gè)int把所有的都映射過(guò)來(lái),然后我想要第幾位再?gòu)睦锩姘恰?/p>

/**
 * @author zhangxishuo on 2019-02-26
 * 計(jì)算機(jī)狀態(tài)結(jié)構(gòu)體
 */
public class HostStatusStruct extends Structure {

    /**
     * 結(jié)構(gòu)體指針
     */
    public static class ByReference extends HostStatusStruct implements Structure.ByReference {
    }

    /**
     * 結(jié)構(gòu)體具體的值
     */
    public static class ByValue extends HostStatusStruct implements Structure.ByValue {
    }

    public int value;

    public int getRev() {
        return value & 0x3FFFFF;
    }

    public int getCopyStatus() {
        return (value >> 23) & 0x3;
    }

    public int getTimeout() {
        return (value >> 26) & 0x1;
    }

    public int getDisconnect() {
        return (value >> 27) & 0x1;
    }

    public int getRev1() {
        return (value >> 28) & 0x1;
    }

    public int getOsLogoned() {
        return (value >> 29) & 0x1;
    }

    public int getLogoned() {
        return (value >> 30) & 0x1;
    }

    public int getOnline() {
        return (value >> 31) & 0x1;
    }

    @Override
    protected List getFieldOrder() {
        return Collections.singletonList("value");
    }
}

至此,功能完成。

總結(jié)

又過(guò)去了忙碌的一周,很高興我們的新項(xiàng)目已經(jīng)完成大半。

感謝潘佳琦與李宜衡在本項(xiàng)目中的支持,第一次用Angular,好多地方我也不懂,我先學(xué)著,然后設(shè)計(jì)一套架構(gòu)付諸實(shí)踐,潘佳琦與李宜衡也都能遵從我制定的規(guī)范。

起初,我也提出了許多錯(cuò)誤的規(guī)范,但當(dāng)我用著用著發(fā)現(xiàn)原來(lái)那套不行的時(shí)候,及時(shí)改正,修改架構(gòu)再重新設(shè)計(jì),潘佳琦與李宜衡也在前臺(tái)經(jīng)歷了大約三次的代碼重構(gòu)。

前臺(tái)架構(gòu)變更多次,感覺最后的設(shè)計(jì)還讓人滿意,也能讓他人快速理解這種設(shè)計(jì)理念。

爭(zhēng)取下一個(gè)項(xiàng)目,不使用ng-alain,自己從頭到尾搭建一個(gè)項(xiàng)目骨架。

最后表?yè)P(yáng)一下潘佳琦,上周基本我有一半的時(shí)間都在上課,我能做的就是前一天晚上把任務(wù)建好,然后寫一些基礎(chǔ)代碼或示例代碼,然后給潘佳琦講,再讓他去寫。

潘佳琦效率還是很高的,我記得周一的時(shí)候建了一堆任務(wù),我想怎么著也得寫兩天吧,當(dāng)我上課回來(lái),發(fā)現(xiàn)“當(dāng)當(dāng)當(dāng)”,潘佳琦都給寫完了,代碼也十分的規(guī)范。

對(duì)小組員的開發(fā)效率在心中也有了一個(gè)重新的定位。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/73494.html

相關(guān)文章

  • Elastic Search搜索引擎在SpringBoot中的實(shí)踐

    摘要:注本文首發(fā)于公眾號(hào),可長(zhǎng)按或掃描下面的小心心來(lái)訂閱實(shí)驗(yàn)環(huán)境版本版本首先當(dāng)然需要安裝好環(huán)境,最好再安裝上可視化插件來(lái)便于我們直觀地查看數(shù)據(jù)。 showImg(https://segmentfault.com/img/remote/1460000015723674); 注: 本文首發(fā)于 My 公眾號(hào) CodeSheep ,可 長(zhǎng)按 或 掃描 下面的 小心心 來(lái)訂閱 ↓ ↓ ↓ showI...

    Me_Kun 評(píng)論0 收藏0
  • Java 外部函數(shù)接口:JNI, JNA, JNR

    摘要:我們知道,發(fā)起函數(shù)調(diào)用,需要構(gòu)造一個(gè)棧幀。構(gòu)造棧幀的具體實(shí)現(xiàn)細(xì)節(jié)的選擇,被稱為調(diào)用慣例。要想完成這個(gè)函數(shù)調(diào)用邏輯,就要運(yùn)行時(shí)構(gòu)造棧幀,生成參數(shù)壓棧和清理堆棧的工作。目前,幾乎支持全部常見的架構(gòu)。 原文:http://nullwy.me/2018/01/java...如果覺得我的文章對(duì)你有用,請(qǐng)隨意贊賞 遇到的問(wèn)題 前段時(shí)間開發(fā)的時(shí)候,遇到一個(gè)問(wèn)題,就是如何用 Java 實(shí)現(xiàn) chdir...

    pubdreamcc 評(píng)論0 收藏0
  • 一個(gè)簡(jiǎn)單的JNA使用例子

    摘要:提供了這個(gè)技術(shù)來(lái)實(shí)現(xiàn)調(diào)用和程序,但實(shí)現(xiàn)起來(lái)比較麻煩,所以后來(lái)公司在的基礎(chǔ)上實(shí)現(xiàn)了一個(gè)框架使用這個(gè)框架可以減輕程序員的負(fù)擔(dān),使得調(diào)用和容易很多。 使用JAVA語(yǔ)言開發(fā)程序比較高效,但有時(shí)對(duì)于一些性能要求高的系統(tǒng),核心功能可能是用C或者C++語(yǔ)言編寫的,這時(shí)需要用到JAVA的跨語(yǔ)言調(diào)用功能。JAVA提供了JNI這個(gè)技術(shù)來(lái)實(shí)現(xiàn)調(diào)用C和C++程序,但JNI實(shí)現(xiàn)起來(lái)比較麻煩,所以后來(lái)SUN公司在...

    winterdawn 評(píng)論0 收藏0
  • Java調(diào)用dll文件

    摘要:目錄創(chuàng)建創(chuàng)建項(xiàng)目與工具項(xiàng)目與工具步驟與代碼步驟與代碼使用調(diào)用使用調(diào)用項(xiàng)目與工具項(xiàng)目與工具步驟與代碼步驟與代碼實(shí)際效果實(shí)際效果參考鏈接參考鏈接創(chuàng)建項(xiàng)目與工具步驟與代碼使用創(chuàng)建動(dòng)態(tài)鏈接庫(kù)項(xiàng)目設(shè)置項(xiàng)目名與項(xiàng)目 目錄 1 C++創(chuàng)建dll 1.1 項(xiàng)目與工具 1.2 步驟與代碼 2 Java使用JN...

    Jeff 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<