• 基于C语言的java串口通信程序


    目录

    1.前言

    2.windows  串口通信API

    3.JAVA-JNI  java程序调用C++程序

    4.C/C++封装  动态运行库

    一、前言

      写这个博客主要是因为自己想用java写一个小小的后端服务器,其中要处理由51单片机传送来的一些数据。单片机的数据由USB转串口发送至上位机,要处理这些数据,就会用到windows提供一些API( Application Programming Interface,应用程序接口 )。java在安装了相关的包后,比如JNative.jar,可以直接用该包提供的接口来进行调用windowsAPI。但是我才接触java。而且整个作业,我仅仅只要一部分来处理这个数据。安装一个java包,实在是大可不必,所以就用C/C++来写一个的终端,封装一下放在java程序里面。

    二、windows串口通信API

      2.1   工具VC++6.0

      2.2   概述:windows操作系统的设备无关性将所有的外设都当做文件来操作,那么我们写串口通信就直接将串口当做文件来读写。那么我们打开串口后一定要记得关闭,这个很重要

      2.3   串口通信程序概述

    2.3.1 打开/关闭串口

    HANDLE WINAPI CreateFileW(
        LPCWSTR lpFileName,                 
        DWORD dwDesiredAccess,                        
        DWORD dwShareMode,                              //共享模式
        LPSECURITY_ATTRIBUTES lpSecurityAttributes,    //安全属性
        DWORD dwCreationDisposition,                  //指定文件的动作
        DWORD dwFlagsAndAttributes,                  //文件属性---不指定就默认为同步IO 
        HANDLE hTemplateFile                        //模板文件
        );
    
    BOOL WINAPI CloseHandle(
           HANDLE hObject
        );
    

    返回值:一个串口的句柄。
    参数解释:
    lpFileName——串口名字。 当为COM1~COM9的时候可以直接写入但是大于10会有另外的写法。以COM10为例:.COM10
    lpFileName——打开方式。 简单来说这个就是打开文件是读还是写。GENERIC_READ(读)|GENERIC_WRITE(写)。还有其它的两个值,详细请在编辑器中直接按下F12看看他们的定义。
    如果我们要定义一个同步IO的话,我们的打开方式必须要有读动作。
    dwShareMode指定该端口的共享属性。 对于不能共享的串口,它必须设置为0。这就是文件与通信设备之间的主要差异之一。如果在当前的应用程序调用CreateFile()时,另一个应用程序已经打开了串口,该函数就会返回错误代码,原因是两个应用程序不能共享一个端口。然而,同一个应用程序的多个线程可以共享由CreateFile()返回的端口句柄,并且根据安全性属性设置,该句柄可以被打开端口的应用程序的子程序所继承。
    dwCreationDisposition指定文件的动作。 指定如果CreateFile()正在被已有的文件调用时应采取的动作。因为串口总是存在,fdwCreate必须设置成OPEN_EXISTING。该标志告诉Windows不用企图创建新端口,而是打开已经存在的端口。
    调用该函数后,如果没有穿件成功将会返回INVALID_HANDLE_VALUE

    2.3.2 配置串口通信

    • (1) 当我们设置同步IO通信的时候,需要设置一下通信超时。一般情况下,我们用GetCommTimeouts来获得COMMTIMEOUTS结构体,再利用SetCommTimeouts来写入。
    BOOL WINAPI GetCommTimeouts(
        HANDLE hFile,
        LPCOMMTIMEOUTS lpCommTimeouts
        );
    
    BOOL WINAPI SetCommTimeouts(
        HANDLE hFile,
        LPCOMMTIMEOUTS lpCommTimeouts
        );
    

    COMMTIMEOUTS

    typedef struct _COMMTIMEOUTS {
        DWORD ReadIntervalTimeout;          /* 设置两个字符之前的最大读取时间 */
        DWORD ReadTotalTimeoutMultiplier;   /* 设置每个字符的读取时间        */
        DWORD ReadTotalTimeoutConstant;     /* 设置所有字符读取的最大时间    */
        DWORD WriteTotalTimeoutMultiplier;  /* 设置每个字符的写入时间       */
        DWORD WriteTotalTimeoutConstant;    /* 设置所有字符的写入时间      */
    } COMMTIMEOUTS,*LPCOMMTIMEOUTS;
    
    
    • (2) 设置波特率等相关参数
      仍然先用GetCommState得到DCB结构,修改其中的某些参数后再用SetCommState写入DCB结构。
    BOOL WINAPI GetCommState(
        HANDLE hFile,
        LPDCB lpDCB
        );
    BOOL WINAPI SetCommState(
        HANDLE hFile,
        LPDCB lpDCB
        );
    

    DCB数据结构我们初级学者需要关注:波特率、校验位、停止位、发送数据位数。

    • (3) 设置缓冲区大小,根据程序要接收/发送的数据大小来决定。
    BOOL WINAPI SetupComm(
        HANDLE hFile,
        DWORD dwInQueue,
        DWORD dwOutQueue
        );
    
    
    
    • (4) 读取/写入数据
    BOOL WINAPI ReadFile(
        HANDLE hFile,
        LPVOID lpBuffer,                  //存放数据的缓冲区
        DWORD nNumberOfBytesToRead,       //一次想要读入的数据长度
        LPDWORD lpNumberOfBytesRead,      //实际读入的数据长度
        LPOVERLAPPED lpOverlapped      
        );
    
    BOOL WINAPI WriteFile(
        HANDLE hFile,
        LPCVOID lpBuffer,
        DWORD nNumberOfBytesToWrite,
        LPDWORD lpNumberOfBytesWritten,
        LPOVERLAPPED lpOverlapped
        );
    

    2.3.3 串口缓冲区配置

    在程序运行的时候,应该保证设置的缓冲区是“干净”的。所以在读数据或者写数据之前,可以先清空一下缓冲区。

    //清空缓冲区
    BOOL WINAPI PurgeComm(
        HANDLE hFile,
        DWORD dwFlags
        );
    
    //清除错误
    BOOL WINAPI ClearCommError(
        HANDLE hFile,
        LPDWORD lpErrors,
        LPCOMSTAT lpStat
        );
    
    

    2.4完整的读串口代码

    #include <stdio.h>`
    #include <windows.h>
    int Comm(int nBaud,int parity,int bytesize,int stopbits,int accdatalength,char rBuf[])
    {								//缓冲区
    	DWORD rSize = 0;
    	DWORD dwError;										//清除错误
    	COMSTAT cs;				
    	COMMTIMEOUTS timeouts;								//超时数据结构
    	DCB dcb;											//串口通信配置文件---用LPDCB类型会报错
    	HANDLE hCom;										//串口的句柄(实例)| the instance of com
    	hCom = CreateFile("COM3",							//串口的名字
    					   GENERIC_READ | GENERIC_WRITE,    //串口打开方式
    					   0,								//共享方式					
    					   NULL,							//安全属性
    					   OPEN_EXISTING,					//指定文件的动作
    					   0,								//文件属性---不指定就默认为同步IO
    					   NULL								//指向模板文件的句柄
    					   );
    	if(hCom == INVALID_HANDLE_VALUE)
    	{
    		return -1;
    	}
    ///////////////////////////////////////
    //同步IO需要设置读数据超时
    //////////////////////////////////////
    	if(!(GetCommTimeouts(hCom,&timeouts)))		//获的COMMTIMEOUTS结构失败!
    	{
    		CloseHandle(hCom);
    	}
    	timeouts.ReadIntervalTimeout = 1000;			//读取每个字符之间的超时
    	timeouts.ReadTotalTimeoutMultiplier = 500;		//读取一个字符的超时
    	timeouts.ReadTotalTimeoutConstant=5000;			//固定总超时
    	timeouts.WriteTotalTimeoutConstant = 0;			//写入字符之间超时
    	timeouts.WriteTotalTimeoutMultiplier = 0;		//写入字符总超时
    	if(!(SetCommTimeouts(hCom,&timeouts)))			//设置COMMTIMEOUTS结构失败
    	{
    		CloseHandle(hCom);
    	}
    ////////////////////////////////////////
    //设置缓冲区大小
    ///////////////////////////////////////
    	if(!SetupComm(hCom,500,500))				//设置读写缓冲区失败
    	{
    		CloseHandle(hCom);
    	}
    //////////////////////////////////////
    //设置波特率等其它读文件配置
    /////////////////////////////////////
    	if(GetCommState(hCom,&dcb)==0)			//获得DCB数据失败
    	{
    		CloseHandle(hCom);
    	}
    	//dcb.DCBlength = sizeof(DCB);
    	dcb.BaudRate = nBaud;					//波特率为4800
    	dcb.Parity = parity;					//校验方式为无校验
    	dcb.ByteSize = bytesize;						//数据位为8位
    	dcb.StopBits = stopbits;				//停止位为1位
    	if (!SetCommState(hCom,&dcb))			//设置串口通信配置项失败
    	{
    		CloseHandle(hCom);
    	}
    
    //////////////////////////////////////
    //清除缓冲区
    /////////////////////////////////////
    	PurgeComm(hCom,PURGE_RXCLEAR|PURGE_TXCLEAR);
    ///////////////////////////////////////
    //清除错误
    ///////////////////////////////////////
    	if(!(ClearCommError(hCom,&dwError,&cs)))
    	{
    		CloseHandle(hCom);
    	}
    ////////////////////////////////////////////
    //开始读取缓冲口的数据
    ///////////////////////////////////////////
    
    	//读取串口数据
    	if(INVALID_HANDLE_VALUE != hCom)
    	{
    		WriteFile
    		ReadFile(hCom,rBuf,accdatalength,&rSize,NULL);
    		printf("%d 
    ",rSize);
    		if(rSize)
    		{
    			CloseHandle(hCom);
    			return 1;
    			
    		}
    		else
    		{
    			CloseHandle(hCom);
    			return 0;
    		}
    	}
    	else
    	{
    		CloseHandle(hCom);
    		return 2;
    	}	
    }
    void main()
    {
    	int i;
    	char buf[18] = {0};
    	int a,b,c,d,e;
    	printf("请输入相关参数:");
    	scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
    	while(1)
    	{
    		if(Comm(a,b,c,d,e,buf)==1)
    		{
    			for(i=0;i<17;i++)
    			{
    				printf("%c ",buf[i]);
    			}
    			printf("
    ");
    		}
    		else
    		{
    			printf("%d 
    ",Comm(a,b,c,d,e,buf));
    			break;
    		}
    	}
    	
    }
    

    运行结果

    三、JAVA-JNI  java程序调用C++程序

      参考博客
      在写java程序调用C程序之前,写过C#程序调用用C#封装好的dll程序。然后,我以为,java程序调用C程序也可以直接把C封装好的dll程序拿过来直接用就好。结果就是一直报错。那么接下来就是正确的调用方式。

    工具eclipse

    3.1

      首先在新建一个类,类的名字随意。最好加上main()函数方便我们进行模块调试。在这个类里面。在这个类里面我们要自己定义将会用C/C++实现的函数。并且必须用到java提供的 System.loadLibrary()函数。如下:
    `

    
    public class Com {
    	
    	static {
    		System.loadLibrary("CommDLL");			//静态语句块,保证在创建该类的时候,该方法必须且只会调用一次。参数就是编写的动态库名称
    	}
    	public native int Comm(int nBaud,int parity,int bytesize,int stopbits,int accdatalength,String ComName,char[] rBuf);//将要用C/C++实现的函数
    	public static void main(String[] args) {
    	      int term = new Com().Comm(4800, 0, 8, 0, 17,"COM3", Buffer);
    			
    	}	
    }
    
    

    `
    注:native 关键字表示,这个函数为本地函数。尽管没用java语言实现,但它有自己的实体。

    3.2

      找到刚编写的java源程序文件所在的位置。然后如下操作:

      注:马赛克的位置是暂时还不该有的文件

      进入控制台:

      输入 javac -d ./ Com.java 。即是根据将java文件经过编译生成二进制文件(class文件)

      输入 javac -h ./ Com.java 生成相关的头文件。

      注:如果报错:'javac不是内部或外部命令,也不是可运行的程序或批处理文件。' 请参考相关博客添加相关的环境变量。参考博客

    3.3

      在生成了相关的库文件的编写后。我们要用这个库文件有两种办法。

    • 1:直接将生成的dll文件加入默认的环境变量里面。( 但是不是很推荐这个办法,因为我们编写的库,仅仅只是在自己的程序上用一用。没有很大的普适性。
    • 2:将生成的dll文件拷贝到自己源文件下面。同时配置一下自己的java程序。
         右键src--->properties--->Native Library--->Workspace

    3.4

    运行代码:

    
    public class Com {
    	
    	static {
    		System.loadLibrary("CommDLL");			//静态语句块,保证在创建该类的时候,该方法必须且只会调用一次。
    	}
    	public native int Comm(int nBaud,int parity,int bytesize,int stopbits,int accdatalength,String ComName,byte[] rBuf);
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		byte[] Buffer = new byte[18];
    		while(true)
    		{
    			int term = new Com().Comm(4800, 0, 8, 0, 17,"COM3", Buffer);
    			if(term==1)
    			{
    				for(int i=0;i<17;i++)
    				{
    					System.out.print(Buffer[i]+" ");
    					
    				}
    				System.out.println();
    			}
    		}
    		
    	}	
    }
    
    

    运行结果

    四、C/C++封装动态运行库

    4.1:关于工具

      一开始用的工具是VC++6.0,尽管工具有点老,但是它足够小。动态库编好了,在eclipse上面运行的时候,出现了错误,大致意思就是:“32位的动态库,没有办法在64位的设备上面”。 如果,我还想继续使用这个动态库,已知的解决办法就是:下载一个32位的java   JDK包。但是,相比配置一个可以运行32位的环境,我更加倾向于编译生成一个64位的动态运行库。然后,我就把代码粘到了VS上面。一般写代码我不太喜欢在VS上面,虽然它的功能很强太,但是我的电脑负载它真的很费力。

    4.2 用JNI编写本地函具体步骤

       * 1:建立DLL程序:文件--->新建--->项目--->windows桌面--->动态链接库

    4.2 代码细节

       * 1:新建一个头文件,把在第三节里面生成的头文件内容复制粘贴过来




       * 2:具体cpp文件实现。
    当我把VC里面的代码直接粘贴过来的时候,就直接报错了。const char* 不可以转换为LPCWSTR。我想强制转化成LPCSTTR那肯定不可以的,但是强制转化为wchar *这个是可以的。因为报错的原因就是函数createFile()想要的文件名字应该是宽字符传进去的。但是当时我只解用了将普通字符转成宽字符的函数 MultiByteToWideChar ,不了解两种字符的可以自行百度一下。用了这个函数后报错没有了。
    但是,为了程序的健壮性我决定,把串口的名字暴露出来。然后新的问题出现了,当我想为了适应之前的程序,把串口的名字当中字符数组传进来的时候。java程序又报错,所以编译器太智能了也让人伤心。Java这边发现的我传入的就是一串字符,马上要求我把参数改成字符串类型。那也没办法,我没有能力自己开发一个IDE,所以就把string 传了进去。但是,我们知道C语言其实没有stirng这种类型,后来我又加了一点C++的代码,这样才勉强有了字符串这种类型。好吧,用函数把jstring 类型在转成宽字符类型。经过这次的修改,代码可以单独在VS里面跑起来了。
    VS单独运行代码:

    #include <iostream>
    #include<stdlib.h>
    #include<windows.h>
    using std::string;
    int Comm(int nBaud, int parity, int bytesize, int stopbits, int accdatalength,string comName, char rBuf[])
    {
    	DWORD rSize = 0;
    	DWORD dwError;										//清除错误
    	COMSTAT cs;
    	COMMTIMEOUTS timeouts;								//超时数据结构
    	DCB dcb;											//串口通信配置文件---用LPDCB类型会报错
    	HANDLE hCom;										//串口的句柄(实例)| the instance of com
    //////////////////////////////////////////////////////////////////////
    //将string转换为LPCWSTR类型
    //////////////////////////////////////////////////////////////////////
    	int len = comName.length();
    	WCHAR buffer[256];
    	///////memset原型---extern void *memset(void *buffer, int c, int count) buffer:为指针或是数组,c:是赋给buffer的值,count:是buffer的长度.//////
    	memset(buffer, 0, sizeof(buffer));		//作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法
    	MultiByteToWideChar(CP_ACP, 0, comName.c_str(), (len+1), buffer, sizeof(buffer) / sizeof(buffer[0]));
    	printf("%d
    ", buffer[0]);
    	hCom = CreateFile(buffer,							//串口的名字
    		GENERIC_READ | GENERIC_WRITE,    //串口打开方式
    		0,								//共享方式					
    		NULL,							//安全属性
    		OPEN_EXISTING,					//指定文件的动作
    		0,								//文件属性---不指定就默认为同步IO
    		NULL								//指向模板文件的句柄
    	);
    	if (hCom == INVALID_HANDLE_VALUE)
    	{
    		return -1;
    	}
    	///////////////////////////////////////
    	//同步IO需要设置读数据超时
    	//////////////////////////////////////
    	if (!(GetCommTimeouts(hCom, &timeouts)))		//获的COMMTIMEOUTS结构失败!
    	{
    		CloseHandle(hCom);
    	}
    	timeouts.ReadIntervalTimeout = 1000;			//读取每个字符之间的超时
    	timeouts.ReadTotalTimeoutMultiplier = 500;		//读取一个字符的超时
    	timeouts.ReadTotalTimeoutConstant = 5000;			//固定总超时
    	timeouts.WriteTotalTimeoutConstant = 0;			//写入字符之间超时
    	timeouts.WriteTotalTimeoutMultiplier = 0;		//写入字符总超时
    	if (!(SetCommTimeouts(hCom, &timeouts)))			//设置COMMTIMEOUTS结构失败
    	{
    		CloseHandle(hCom);
    	}
    	////////////////////////////////////////
    	//设置缓冲区大小
    	///////////////////////////////////////
    	if (!SetupComm(hCom, 500, 500))				//设置读写缓冲区失败
    	{
    		CloseHandle(hCom);
    	}
    	//////////////////////////////////////
    	//设置波特率等其它读文件配置
    	/////////////////////////////////////
    	if (GetCommState(hCom, &dcb) == 0)			//获得DCB数据失败
    	{
    		CloseHandle(hCom);
    	}
    	//dcb.DCBlength = sizeof(DCB);
    	dcb.BaudRate = nBaud;					//波特率为4800
    	dcb.Parity = parity;					//校验方式为无校验
    	dcb.ByteSize = bytesize;						//数据位为8位
    	dcb.StopBits = stopbits;				//停止位为1位
    	if (!SetCommState(hCom, &dcb))			//设置串口通信配置项失败
    	{
    		CloseHandle(hCom);
    	}
    
    	//////////////////////////////////////
    	//清除缓冲区
    	/////////////////////////////////////
    	PurgeComm(hCom, PURGE_RXCLEAR | PURGE_TXCLEAR);
    	///////////////////////////////////////
    	//清除错误
    	///////////////////////////////////////
    	if (!(ClearCommError(hCom, &dwError, &cs)))
    	{
    		CloseHandle(hCom);
    	}
    	////////////////////////////////////////////
    	//开始读取缓冲口的数据
    	///////////////////////////////////////////
    
    		//读取串口数据
    	if (INVALID_HANDLE_VALUE != hCom)
    	{
    		ReadFile(hCom, rBuf, accdatalength, &rSize, NULL);
    		printf("%d 
    ", rSize);
    		if (rSize)
    		{
    			CloseHandle(hCom);
    			return 1;
    
    		}
    		else
    		{
    			CloseHandle(hCom);
    			return 0;
    		}
    	}
    	else
    	{
    		CloseHandle(hCom);
    		return 2;
    	}
    }
    void main()
    {
    	int i;
    	char buf[18] = { 0 };
    	int a, b, c, d, e;
    	char ComName[6];
    	printf("请输入相关参数:");
    	std::cin >> a >> b >> c >> d >> e>>ComName;
    	while (1)
    	{
    		int t = Comm(a, b, c, d, e, ComName, buf);
    		if (t == 1)
    		{
    			for (i = 0; i < 17; i++)
    			{
    				printf("%c ", buf[i]);
    			}
    			printf("
    ");
    		}
    		else
    		{
    			printf("%d
    ", t);
    			break;
    		}
    	}
    
    }
    
    
    • 3:JNI中基本类型的处理
        完成这个作业之前我只是知道有JNI这个知识点,但是确实没有系统的学习过。但是我就自己学的一点点东西可以总结一下。java里面的基础类型可以放到C/C++里面使用但是像数组之类的数据类型,必须有Java认同的类型稍作处理,才可以在C/C++的环境里面运行。具体请参考:参考博客这片博客好像是sun官网的中翻,值得参考。
    • 4:成功的DLL源代码:
    #include "pch.h"
    #include "comm.h"
    #include <iostream>
    #include <stdlib.h>
    #include <windows.h>
    using std::string;
    /////////////////////////////////////////////////////////////////////////
    //
    JNIEXPORT jint JNICALL Java_Com_Comm(JNIEnv* env, jobject, jint nBaud, jint parity, jint bytesize, jint stopbits, jint accdatalength,jstring comName, jbyteArray rBuf)
    {	DWORD rSize = 0;
    	DWORD dwError;										//清除错误
    	COMSTAT cs;
    	COMMTIMEOUTS timeouts;								//超时数据结构
    	DCB dcb;											//串口通信配置文件---用LPDCB类型会报错
    	HANDLE hCom;										//串口的句柄(实例)| the instance of com
    	BYTE rBuffer[255];
    //////////////////////////////////////////////////////////////////////
    //将jstring转换为LPCWSTR类型
    //////////////////////////////////////////////////////////////////////
    	WCHAR* buffer = (WCHAR*)env->GetStringChars(comName,NULL);
    	hCom = CreateFile(buffer,							//串口的名字
    		GENERIC_READ | GENERIC_WRITE,    //串口打开方式
    		0,								//共享方式					
    		NULL,							//安全属性
    		OPEN_EXISTING,					//指定文件的动作
    		0,								//文件属性---不指定就默认为同步IO
    		NULL								//指向模板文件的句柄
    	);
    	if (hCom == INVALID_HANDLE_VALUE)
    	{
    		return -1;
    	}
    	///////////////////////////////////////
    	//同步IO需要设置读数据超时
    	//////////////////////////////////////
    	if (!(GetCommTimeouts(hCom, &timeouts)))		//获的COMMTIMEOUTS结构失败!
    	{
    		CloseHandle(hCom);
    	}
    	timeouts.ReadIntervalTimeout = 1000;			//读取每个字符之间的超时
    	timeouts.ReadTotalTimeoutMultiplier = 500;		//读取一个字符的超时
    	timeouts.ReadTotalTimeoutConstant = 5000;			//固定总超时
    	timeouts.WriteTotalTimeoutConstant = 0;			//写入字符之间超时
    	timeouts.WriteTotalTimeoutMultiplier = 0;		//写入字符总超时
    	if (!(SetCommTimeouts(hCom, &timeouts)))			//设置COMMTIMEOUTS结构失败
    	{
    		CloseHandle(hCom);
    	}
    	////////////////////////////////////////
    	//设置缓冲区大小
    	///////////////////////////////////////
    	if (!SetupComm(hCom, 500, 500))				//设置读写缓冲区失败
    	{
    		CloseHandle(hCom);
    	}
    	//////////////////////////////////////
    	//设置波特率等其它读文件配置
    	/////////////////////////////////////
    	if (GetCommState(hCom, &dcb) == 0)			//获得DCB数据失败
    	{
    		CloseHandle(hCom);
    	}
    	//dcb.DCBlength = sizeof(DCB);
    	dcb.BaudRate = nBaud;					//波特率为4800
    	dcb.Parity = parity;					//校验方式为无校验
    	dcb.ByteSize = bytesize;						//数据位为8位
    	dcb.StopBits = stopbits;				//停止位为1位
    	if (!SetCommState(hCom, &dcb))			//设置串口通信配置项失败
    	{
    		CloseHandle(hCom);
    	}
    
    	//////////////////////////////////////
    	//清除缓冲区
    	/////////////////////////////////////
    	PurgeComm(hCom, PURGE_RXCLEAR | PURGE_TXCLEAR);
    	///////////////////////////////////////
    	//清除错误
    	///////////////////////////////////////
    	if (!(ClearCommError(hCom, &dwError, &cs)))
    	{
    		CloseHandle(hCom);
    	}
    	////////////////////////////////////////////
    	//开始读取缓冲口的数据
    	///////////////////////////////////////////
    
    		//读取串口数据
    	if (INVALID_HANDLE_VALUE != hCom)
    	{
    		ReadFile(hCom, &rBuffer, accdatalength, &rSize, NULL);
    		if (rSize)
    		{
    			jbyte* term;								//将RBuffer中的值赋给rBuf
    			term = env->GetByteArrayElements(rBuf,FALSE);
    			for (int i = 0; i < accdatalength; i++)
    			{
    				term[i] = rBuffer[i];
    			}
    			env->ReleaseByteArrayElements(rBuf,term, JNI_COMMIT);
    			CloseHandle(hCom);
    			return 1;
    
    		}
    	}
    	else
    	{
    		CloseHandle(hCom);
    		return 1;
    	}
    	env->ReleaseStringChars(comName,(jchar *)buffer);			//释放空间
    	CloseHandle(hCom);
    	return 2;
    
    }
    
    

    注:代码写在自己新建的和头文件同名的自己建立的源文件(.cpp)里面。

    4.3 配置

    在生成DLL文件之前,我们还必须做一些重要的配置。

    • 1:把java jdk里面的一些文件拷贝到DLL文件里面去。

      将框起来的三个头文件复制到DLL源程序的文件里面。

    • 2:修改一下DLL项目的配置:

    右键项目 ---> 属性--->VC++目录--->包含目录(把DLL程序所在的文件路径添加进去)

    最后,我们在点击生成。就OK啦。

    到此结束啦,希望可以帮助到你!

  • 相关阅读:
    git注册和基本命令
    thinkphp概述2
    thinkphp概述
    PHP基础知识总结
    phpmyadmin教程
    开发环境wamp3.06 + Zend studio 12 调试配置
    PHP标记风格,编码规范
    PHP开发工具 zend studio
    php与ajax技术
    可变参模板template
  • 原文地址:https://www.cnblogs.com/kadcyh/p/14389710.html
Copyright © 2020-2023  润新知