Dec 29

Java JNI学习

    07年的时候就用过JNI这东西了,那时候是为了给项目的J2EE应用写一个授权功能,通过调用vc写的读取硬件id的dll使得cdkey能够跟机器一一对应起来,从而做到控制一个cdkey只能装到一台机器上上。那会儿用的dll是别人写的,java中调用dll也是用的小日本儿写的一个叫jcom的组件,这次决定自己做一遍整个流程.

  1. 编写java文件
    /**
     * Copyright (C), 2009-2010
     * File Name: jni.WinMessage.java
     * Encoding UTF-8
     * Version: 1.0
     * Date: Dec 29, 2009
     * History:	
     */
    package jni;
    
    /**
     *
     * @author (bestirwiny@gmail.com)
     * @version Revision: 1.00 2:12:24 PM
     */
    public class WinMessage
    {
    	static{
    		System.loadLibrary("WinMsgDll");
    	}
    	public native void showMsgBox(String msg);
    }
    

    loadLibrary用于load一个dll,该dll应该在java.library.path定义的路径下啊。

  2. 用javac编译该文件,不用讲。
  3. javah -jni WinMessage,会生成一个jni_WinMessage.h的头文件,下面要做的工作就是dll的编写了。
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include "jni.h"
    /* Header for class jni_WinMessage */
    
    #ifndef _Included_jni_WinMessage
    #define _Included_jni_WinMessage
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     jni_WinMessage
     * Method:    showMsgBox
     * Signature: (Ljava/lang/String;)V
     */
    JNIEXPORT void JNICALL Java_jni_WinMessage_showMsgBox
      (JNIEnv *, jobject, jstring);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    
  4. 创建一个win32动态连接库的工程,将$JAVAHOME/include,$JAVA_HOME/include/win32目录加入到工程需要引用的头文件路径中。
    #include "tchar.h"
    #include "stdlib.h"
    #include "stdio.h"
    #include "AtlBase.h"
    #include "AtlConv.h"
    #include "windows.h"
    #include "jni_WinMessage.h"
    
    /*
     * Class:    
     * Method:    showMsgBox
     * Signature: (Ljava/lang/String;)V
     */
    JNIEXPORT void JNICALL Java_jni_WinMessage_showMsgBox
      (JNIEnv * env, jobject jobj, jstring str){
    	const char * msg;
    	msg = env->GetStringUTFChars(str,0);
    
    	WCHAR* strA;
        int i= MultiByteToWideChar ( CP_UTF8 , 0 ,msg ,-1 ,NULL,0);
    	strA = new WCHAR[i];
    	MultiByteToWideChar ( CP_UTF8 , 0 ,( char * ) msg, -1, strA , i );
    
    	USES_CONVERSION;
    	MessageBox(NULL,strA,_T("Java invoke "),MB_OK);
    	env->ReleaseStringUTFChars(str,msg);
    }
    

    由于win32变成才开始学,所以这个东西弄了好久才弄好,网上的例子中通过GetStringUTFChars取回的msg直接传到MessageBox中用,可我用的是VS2008,直接用会报错误,大致是说不能将const char *转换为LPCWSTR * ,
    LPCWSTR是long pointer constant wide string的意思,是一种wchar_t类型,char类型占用一个byte,而wchar_t占用两个byte,所以这边就要用一个转换 函数,网上查好久才查到MutiByteToWideChar函数,才解决了中文乱码的问题。

  5. 编译完会成成一个dll文件,拷贝到java.library.path下,我是拷贝到了c:\windows下。
  6. 编写一个java类调用上面的WinMessage
    /**
     * Copyright (C), 2009-2010
     * File Name: jni.TestWinMessage.java
     * Encoding UTF-8
     * Version: 1.0
     * Date: Dec 29, 2009
     * History:	
     */
    package jni;
    
    /**
     *
     * @author (bestirwiny@gmail.com)
     * @version Revision: 1.00 4:54:25 PM
     */
    public class TestWinMessage
    {
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args)
    	{
    		WinMessage wm = new WinMessage();
    		wm.showMsgBox("MC Hotdog,哈狗帮!");
    	}
    }
    
  7. ok,这下就完成了从java程序中调用win32 API弹出windows原生的窗口了 。
Dec 29

VC++ Data Type Ranges

 

Type Name

Bytes

Other Names

Range of Values

int

4

signed

–2,147,483,648 to 2,147,483,647

unsigned int

4

unsigned

0 to 4,294,967,295

__int8

1

char

–128 to 127

unsigned __int8

1

unsigned char

0 to 255

__int16

2

short, short int, signed short int

–32,768 to 32,767

unsigned __int16

2

unsigned short, unsigned short int

0 to 65,535

__int32

4

signed, signed int, int

–2,147,483,648 to 2,147,483,647

unsigned __int32

4

unsigned, unsigned int

0 to 4,294,967,295

__int64

8

long long, signed long long

–9,223,372,036,854,775,808 to 9,223,372,036,854,775,807

unsigned __int64

8

unsigned long long

0 to 18,446,744,073,709,551,615

bool

1

none

false or true

char

1

none

–128 to 127 by default

0 to 255 when compiled with /J

signed char

1

none

–128 to 127

unsigned char

1

none

0 to 255

short

2

short int, signed short int

–32,768 to 32,767

unsigned short

2

unsigned short int

0 to 65,535

long

4

long int, signed long int

–2,147,483,648 to 2,147,483,647

unsigned long

4

unsigned long int

0 to 4,294,967,295

long long

8

none (but equivalent to __int64)

–9,223,372,036,854,775,808 to 9,223,372,036,854,775,807

unsigned long long

8

none (but equivalent to unsigned __int64)

0 to 18,446,744,073,709,551,615

enum

varies

none

See Remarks.

float

4

none

3.4E +/- 38 (7 digits)

double

8

none

1.7E +/- 308 (15 digits)

long double

same as double

none

same as double

wchar_t

2

__wchar_t

0 to 65,535

 

 

从MSDN上看到,截取下来以备后用。

 

 

Dec 15

linux多线程编程

1 引言

  线程(thread)技术早在60年代就被提出,但真正应用多线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者。传统的Unix也支持线程的概念,但是在一个进程(process)中只允许有一个线程,这样多线程就意味着多进程。现在,多线程技术已经被许多操作系统所支持,包括Windows/NT,当然,也包括Linux。

Continue reading