首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

JNI Windows 平台開發指南:Visual Studio 專案、中文路徑、陣列傳遞完整實作

     編輯:Java 相關知識

環境需求

  • JDK (64 位元建議) + Visual Studio 2017/2019/2022 (C++ 桌面開發工作負載)
  • 目錄結構:

E:\JNI
├── com\yiluboke\zxy\WriteReadJ.java
└── WriteReadCpp\
    ├── writeReadDo.h
    ├── writeReadDo.cpp
    └── com_yiluboke_zxy_WriteReadJ.cpp

1. Java 類別 (同 Linux 版)


package com.yiluboke.zxy;
public class WriteReadJ {
    public native int writeFile(byte[] data, String filePath);
    public native int readFilePre(String filePath);
    public native byte[] readFile(String filePath);
    static { System.loadLibrary("jniwritereadfile"); } // jniwritereadfile.dll
    public static void main(String[] args) { /* 測試 */ }
}

2. 編譯與產生 Header


cd E:\JNI
javac com\yiluboke\zxy\WriteReadJ.java
javah -jni com.yiluboke.zxy.WriteReadJ
# 產生 com_yiluboke_zxy_WriteReadJ.h

3. C++ 核心實作 (Visual Studio 專案設定:x64、Release、DLL)

writeReadDo.h


#ifndef __WRITEREADDO_H__
#define __WRITEREADDO_H__
typedef unsigned char BYTE;
const int MAXLEN = 1024;
extern BYTE g_data[MAXLEN];
extern int g_len;
int writeFile(BYTE* data, int len, const char* path);
int readFile(const char* path);
#endif

writeReadDo.cpp


#include "writeReadDo.h"
#include 
using namespace std;

BYTE g_data[MAXLEN] = {};
int g_len = 0;

int writeFile(BYTE* data, int len, const char* path) {
    ofstream out(path, ios::out | ios::binary);
    if (!out) return -1;
    out.write((const char*)data, len);
    out.close();
    return 0;
}

int readFile(const char* path) {
    ifstream in(path, ios::in | ios::binary);
    if (!in) return -1;
    in.seekg(0, ios::end);
    int cnt = in.tellg();
    in.seekg(0, ios::beg);
    g_len = min(cnt, MAXLEN);
    in.read((char*)g_data, g_len);
    in.close();
    return 0;
}

com_yiluboke_zxy_WriteReadJ.cpp (JNI 橋接層)


#include "com_yiluboke_zxy_WriteReadJ.h"
#include "writeReadDo.h"
#include 

static const char* ENCODING = "GB2312";

char* Jstring2CStr(JNIEnv* env, jstring jstr, int* outLen) {
    jclass cls = env->FindClass("java/lang/String");
    jmethodID mid = env->GetMethodID(cls, "getBytes", "(Ljava/lang/String;)[B");
    jstring enc = env->NewStringUTF(ENCODING);
    jbyteArray arr = (jbyteArray)env->CallObjectMethod(jstr, mid, enc);
    
    jsize len = env->GetArrayLength(arr);
    *outLen = len + 1;
    jbyte* elems = env->GetByteArrayElements(arr, JNI_FALSE);
    
    char* result = new char[len + 1];
    memcpy(result, elems, len);
    result[len] = '\0';
    
    env->ReleaseByteArrayElements(arr, elems, JNI_ABORT);
    return result;
}

JNIEXPORT jint JNICALL Java_com_yiluboke_zxy_WriteReadJ_writeFile(
    JNIEnv* env, jobject, jbyteArray jData, jstring jPath) {
    
    int pathLen;
    char* path = Jstring2CStr(env, jPath, &pathLen);
    jbyte* data = env->GetByteArrayElements(jData, JNI_FALSE);
    jsize len = env->GetArrayLength(jData);
    
    int ret = writeFile((BYTE*)data, (int)len, path);
    
    env->ReleaseByteArrayElements(jData, data, JNI_ABORT);
    delete[] path;
    return ret;
}

JNIEXPORT jint JNICALL Java_com_yiluboke_zxy_WriteReadJ_readFilePre(
    JNIEnv* env, jobject, jstring jPath) {
    
    int pathLen;
    char* path = Jstring2CStr(env, jPath, &pathLen);
    int ret = readFile(path);
    delete[] path;
    return ret;
}

JNIEXPORT jbyteArray JNICALL Java_com_yiluboke_zxy_WriteReadJ_readFile(
    JNIEnv* env, jobject, jstring) {
    
    jbyteArray arr = env->NewByteArray(g_len);
    env->SetByteArrayRegion(arr, 0, g_len, (jbyte*)g_data);
    return arr;
}

4. Visual Studio 專案關鍵設定

  • **平台:x64** (對應 64 位元 JDK),不可為 Win32
  • **組態類型:動態連結庫 (.dll)**
  • **C/C++ → 一般 → 附加包含目錄**:
    $(JAVA_HOME)\include;$(JAVA_HOME)\include\win32
  • **連結器 → 一般 → 輸出檔案**:jniwritereadfile.dll
  • **偵錯 → 命令引數**:com.yiluboke.zxy.WriteReadJ (可直接 F5 偵錯)

5. 執行驗證


cd E:\JNI
java com.yiluboke.zxy.WriteReadJ

常見錯誤排查

完整 Demo 下載

百度網盤:JNI Windows Demo

總結

Windows JNI 核心在 **x64 編譯、GB2312/UTF-8 編碼轉換、byte 陣列 Get/Release 配對、DLL 命名與載入路徑** 。Visual Studio 提供完整偵錯體驗,建議新手優先在 Windows 熟悉 JNI 流程再移植 Linux。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
錯誤原因解決
Can't load IA 32-bit .dll on a AMD 64-bit platformDLL 編譯為 32 位元,JDK 為 64 位元VS 專案平台設為 x64
jni.h not found包含目錄未設定加入 $(JAVA_HOME)/include 及 win32
UnsatisfiedLinkErrorDLL 未在 PATH / java.library.path將 DLL 放在專案根目錄或設定 -Djava.library.path