186
187
struct event_info_struct *master_index = NULL;
190
/*----------------------------------------------------------
193
accept: The JNIEnv and jobj of the thread, the original eis.
194
perform: fill in the needed variables with this threads values
197
comments: java variables (especially JNIEnv) should not be shared
198
between threads. Right now we build a local struct with
199
the thread's info before using the variabls. This is
200
especially true for send_event.
202
See also JNI_OnLoad() if the thread does not have the values
203
----------------------------------------------------------*/
204
struct event_info_struct build_threadsafe_eis(
207
struct event_info_struct *eis
210
struct event_info_struct myeis = *eis;
213
myeis.jclazz = (*env)->GetObjectClass( env, *jobj );
215
myeis.fd = get_java_var( env, *jobj, "fd", "I" );
216
myeis.send_event = (*env)->GetMethodID(
188
225
/*----------------------------------------------------------
189
226
RXTXPort.Initialize
395
432
case B2400: return 2400;
396
433
case B4800: return 4800;
397
434
case B9600: return 9600;
436
case B14400: return 14400;
398
438
case B19200: return 19200;
440
case B28800: return 28800;
399
442
case B38400: return 38400;
400
443
case B57600: return 57600;
444
/* I don't think this is universal.. older UARTs never did these. taj */
446
case B115200: return 115200;
448
#ifdef B128000 /* dima */
449
case B128000: return 128000;
452
case B230400: return 230400;
454
#ifdef B256000 /* dima */
455
case B256000: return 256000;
458
case B460800: return 460800;
461
case B500000: return 500000;
464
case B576000: return 576000;
467
case B921600: return 921600;
470
case B1000000: return 1000000;
471
#endif /* B1000000 */
473
case B1152000: return 1152000;
474
#endif /* B1152000 */
476
case B1500000: return 1500000;
477
#endif /* B1500000 */
479
case B2000000: return 2000000;
480
#endif /* B2000000 */
482
case B2500000: return 2500000;
483
#endif /* B2500000 */
485
case B3000000: return 3000000;
486
#endif /* B3000000 */
488
case B3500000: return 3500000;
489
#endif /* B3500000 */
491
case B4000000: return 4000000;
492
#endif /* B4000000 */
401
493
default: return -1;
667
if( !translate_data_bits( env, &(ttyset.c_cflag), dataBits ) )
759
if( translate_data_bits( env, &(ttyset.c_cflag), dataBits ) )
669
761
report( "set_port_params: Invalid Data Bits Selected\n" );
673
if( !translate_stop_bits( env, &(ttyset.c_cflag), stopBits ) )
765
if( translate_stop_bits( env, &(ttyset.c_cflag), stopBits ) )
675
767
report( "set_port_params: Invalid Stop Bits Selected\n" );
679
if( !translate_parity( env, &(ttyset.c_cflag), parity ) )
771
if( translate_parity( env, &(ttyset.c_cflag), parity ) )
681
773
report( "set_port_params: Invalid Parity Selected\n" );
819
920
case 2400: return B2400;
820
921
case 4800: return B4800;
821
922
case 9600: return B9600;
924
case 14400: return B14400;
822
926
case 19200: return B19200;
928
case 28800: return B28800;
823
930
case 38400: return B38400;
825
931
case 57600: return B57600;
932
/* I don't think this is universal.. older UARTs never did these. taj */
828
case 115200: return B115200;
831
case 230400: return B230400;
834
case 460800: return B460800;
837
case 14400: return B14400;
840
case 28800: return B28800;
934
case 115200: return B115200;
842
936
#ifdef B128000 /* dima */
843
937
case 128000: return B128000;
844
938
#endif /* dima */
940
case 230400: return B230400;
845
942
#ifdef B256000 /* dima */
846
943
case 256000: return B256000;
847
944
#endif /* dima */
946
case 460800: return B460800;
949
case 500000: return B500000;
952
case 576000: return B576000;
955
case 921600: return B921600;
958
case 1000000: return B1000000;
959
#endif /* B1000000 */
961
case 1152000: return B1152000;
962
#endif /* B1152000 */
964
case 1500000: return B1500000;
965
#endif /* B1500000 */
967
case 2000000: return B2000000;
968
#endif /* B2000000 */
970
case 2500000: return B2500000;
971
#endif /* B2500000 */
973
case 3000000: return B3000000;
974
#endif /* B3000000 */
976
case 3500000: return B3500000;
977
#endif /* B3500000 */
979
case 4000000: return B4000000;
980
#endif /* B4000000 */
850
983
/* Handle custom speeds */
909
1044
case STOPBITS_1:
910
1045
(*cflag) &= ~CSTOPB;
911
1046
LEAVE( "RXTXPort:translate_stop_bits" );
913
1048
/* ok.. lets try putting it in and see if anyone notices */
914
1049
case STOPBITS_1_5:
915
translate_data_bits( env, cflag, JDATABITS_5 );
1050
if ( translate_data_bits( env, cflag, JDATABITS_5 ) )
916
1053
case STOPBITS_2:
917
1054
(*cflag) |= CSTOPB;
918
1055
LEAVE( "RXTXPort:translate_stop_bits" );
922
1059
LEAVE( "RXTXPort:translate_stop_bits" );
1061
For some reason the native exceptions are not being caught. Moving this
1062
to the Java side fixed the issue. taj.
923
1063
throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
924
1064
"", "stopbit value not supported" );
1068
JNIEXPORT jint JNICALL RXTXPort(nativeGetFlowControlMode)(JNIEnv *env, jobject jobj, jint fd)
1070
struct termios ttyset;
1073
tcgetattr( fd, &ttyset );
1075
if( ttyset.c_cflag & HARDWARE_FLOW_CONTROL )
1077
ret |= ( FLOWCONTROL_RTSCTS_IN | FLOWCONTROL_RTSCTS_OUT );
1079
if ( ttyset.c_iflag & IXOFF )
1081
ret |= FLOWCONTROL_XONXOFF_IN;
1083
if ( ttyset.c_iflag & IXON )
1085
ret |= FLOWCONTROL_XONXOFF_OUT;
1087
return( (jint) ret );
1089
JNIEXPORT jint JNICALL RXTXPort(nativeGetParity)(JNIEnv *env, jobject jobj, jint fd)
1091
struct termios ttyset;
1093
if( tcgetattr( fd, &ttyset ) < 0 )
1095
report("nativeGetParity: tcgetattr failed\n");
1099
if ( ( ttyset.c_cflag & PARENB ) &&
1100
( ttyset.c_cflag & PARODD ) &&
1101
( ttyset.c_cflag & CMSPAR ) )
1103
return( JPARITY_MARK );
1105
else if ( ttyset.c_cflag & ( PARENB &&
1106
ttyset.c_cflag & CMSPAR ) )
1108
return( JPARITY_SPACE );
1111
if ( ttyset.c_cflag & PARENB &&
1112
ttyset.c_cflag & PARODD )
1114
return( JPARITY_ODD );
1116
else if ( ttyset.c_cflag & PARENB )
1118
return( JPARITY_EVEN );
1122
return( JPARITY_NONE );
928
1126
/*----------------------------------------------------------
929
1127
translate_parity
931
accept: javx.comm.SerialPort.PARITY_* constant
1129
accept: javax.comm.SerialPort.PARITY_* constant
932
1130
perform: set proper termios c_cflag bits
933
return: 1 if successful
934
0 if an exception is thrown
935
1132
exceptions: UnsupportedCommOperationException
936
1133
comments: The CMSPAR bit should be used for 'mark' and 'space' parity,
937
1134
but it's not in glibc's includes. Oh well, rarely used anyway.
939
1136
int translate_parity( JNIEnv *env, tcflag_t *cflag, jint parity )
941
1138
ENTER( "translate_parity" );
942
(*cflag) &= ~(PARENB | PARODD);
1140
(*cflag) &= ~(PARENB | PARODD | CMSPAR );
943
1142
switch( parity ) {
944
1143
case JPARITY_NONE:
945
1144
LEAVE( "translate_parity" );
947
1146
case JPARITY_EVEN:
948
1147
(*cflag) |= PARENB;
949
1148
LEAVE( "translate_parity" );
951
1150
case JPARITY_ODD:
952
1151
(*cflag) |= PARENB | PARODD;
953
1152
LEAVE( "translate_parity" );
956
1155
case JPARITY_MARK:
957
1156
(*cflag) |= PARENB | PARODD | CMSPAR;
958
1157
LEAVE( "translate_parity" );
960
1159
case JPARITY_SPACE:
961
1160
(*cflag) |= PARENB | CMSPAR;
962
1161
LEAVE( "translate_parity" );
964
1163
#endif /* CMSPAR */
966
1165
printf("Parity missed %i\n", (int) parity );
969
1168
LEAVE( "translate_parity" );
1170
For some reason the native exceptions are not being caught. Moving this
1171
to the Java side fixed the issue. taj.
970
1172
throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
971
1173
"", "parity value not supported" );
974
1177
#if !defined(TIOCSERGETLSR) && !defined(WIN32)
975
1178
/*----------------------------------------------------------
1132
1335
pthread_detach( tid );
1133
1336
#endif /* TIOCSERGETLSR */
1134
1337
report("init_threads: get eis\n");
1135
jeis = (*eis->env)->GetFieldID( eis->env, eis->jclazz, "eis", "I" );
1338
jeis = (*eis->env)->GetFieldID( eis->env, eis->jclazz, "eis", "J" );
1136
1339
report("init_threads: set eis\n");
1137
(*eis->env)->SetIntField(eis->env, *eis->jobj, jeis, ( jint ) eis );
1340
(*eis->env)->SetIntField(eis->env, *eis->jobj, jeis, ( size_t ) eis );
1138
1341
report("init_threads: stop\n");
1139
1342
report_time_end( );
1747
1967
int fd = get_java_var( env, jobj,"fd","I" );
1748
1968
struct serial_struct sstruct;
1970
if ( ioctl( fd, TIOCGSERIAL, &sstruct ) < 0 )
1975
sstruct.baud_base = (int) BaudBase;
1750
1977
if ( sstruct.baud_base < 1 ||
1751
1978
ioctl( fd, TIOCSSERIAL, &sstruct ) < 0 )
1755
return( JNI_FALSE );
1982
return( ( jboolean ) 0 );
1984
throw_java_exception( env, IO_EXCEPTION, "nativeSetBaudBase",
1985
strerror( errno ) );
1986
return( ( jboolean ) 1 );
1757
1988
throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
1758
1989
"nativeSetBaudBase", strerror( errno ) );
1990
return( ( jboolean ) 1 );
1760
1991
#endif /* TIOCGSERIAL */
1821
2056
if ( ioctl( fd, TIOCGSERIAL, &sstruct ) < 0 )
1826
2061
if ( sstruct.custom_divisor < 1 ||
1827
2062
ioctl( fd, TIOCSSERIAL, &sstruct ) < 0 )
1831
return( JNI_FALSE );
2066
return( ( jboolean ) 0 );
2068
throw_java_exception( env, IO_EXCEPTION, "nativeSetDivisor",
2069
strerror( errno ) );
2070
return( ( jboolean ) 1 );
1833
2072
throw_java_exception( env, UNSUPPORTED_COMM_OPERATION,
1834
2073
"nativeSetDivisor", strerror( errno ) );
2074
return( ( jboolean ) 1 );
1836
2075
#endif /* TIOCGSERIAL */
2690
2934
int ret, left, bytes = 0;
2691
2935
long timeLeft, now = 0, start = 0;
2693
2937
struct timeval tv, *tvP;
2940
int flag, count = 0;
2941
struct event_info_struct *eis = ( struct event_info_struct * )
2942
get_java_var( env, *jobj,"eis","J" );
2696
2944
report_time_start();
2945
flag = eis->eventflags[SPE_DATA_AVAILABLE];
2946
eis->eventflags[SPE_DATA_AVAILABLE] = 0;
2697
2948
ENTER( "read_byte_array" );
2698
2949
sprintf(msg, "read_byte_array requests %i\n", length);
2701
2953
if (timeout >= 0)
2702
2954
start = GetTickCount();
2703
while( bytes < length )
2955
while( bytes < length && count++ < 20 ) /* && !is_interrupted( eis ) )*/
2705
2957
if (timeout >= 0) {
2706
2958
now = GetTickCount();
2707
2959
if ( now-start >= timeout )
2961
eis->eventflags[SPE_DATA_AVAILABLE] = flag;
2711
2966
FD_ZERO(&rset);
2724
ret = SELECT(fd + 1, &rset, NULL, NULL, tvP);
2978
/* FIXME HERE Trent */
2980
ret = SELECT( fd + 1, &rset, NULL, NULL, tvP );
2725
2984
if (ret == -1){
2726
2985
report( "read_byte_array: select returned -1\n" );
2727
2986
LEAVE( "read_byte_array" );
2987
eis->eventflags[SPE_DATA_AVAILABLE] = flag;
2731
2992
if ((ret = READ( fd, buffer + bytes, left )) < 0 ){
2732
2993
if (errno != EINTR && errno != EAGAIN){
2733
2994
report( "read_byte_array: read returned -1\n" );
2734
2995
LEAVE( "read_byte_array" );
2996
eis->eventflags[SPE_DATA_AVAILABLE] = flag;
2999
eis->eventflags[SPE_DATA_AVAILABLE] = flag;
2738
3002
else if ( ret ) {
3125
3407
strerror( errno ) );
3128
sprintf( msg, "RXTXPort:readArray: %i %i\n", (int) length, bytes);
3131
LEAVE( "RXTXPort:readArray" );
3411
sprintf( msg, "RXTXPort:readArray: %i %i\n", (int) length, bytes);
3414
LEAVE( "RXTXPort:readArray" );
3419
/*----------------------------------------------------------
3420
RXTXPort.nativeClearCommInput
3423
perform: try to clear the input.
3424
return: true on success, false on error
3426
comments: This is an extension to commapi.
3427
----------------------------------------------------------*/
3428
JNIEXPORT jboolean JNICALL RXTXPort(nativeClearCommInput)( JNIEnv *env,
3431
int fd = get_java_var( env, jobj, "fd", "I" );
3432
if ( tcflush( fd, TCIFLUSH ) )
3433
return( JNI_FALSE );
3436
/*----------------------------------------------------------
3437
RXTXPort.readTerminatedArray
3439
accept: offset (offset to start storing data in the jbarray) and
3440
Length (bytes to read). Terminator - 2 bytes that we
3442
perform: read bytes from the port into a byte array
3443
return: bytes read on success
3445
exceptions: IOException
3446
comments: throws ArrayIndexOutOfBoundsException if asked to
3447
read more than SSIZE_MAX bytes
3448
timeout is not properly handled
3450
This is an extension to commapi.
3451
----------------------------------------------------------*/
3452
JNIEXPORT jint JNICALL RXTXPort(readTerminatedArray)( JNIEnv *env,
3453
jobject jobj, jbyteArray jbarray, jint offset, jint length,
3454
jbyteArray jterminator )
3456
int bytes, total = 0;
3457
jbyte *body, *terminator;
3459
int fd = get_java_var( env, jobj, "fd", "I" );
3460
int timeout = get_java_var( env, jobj, "timeout", "I" );
3463
ENTER( "readArray" );
3464
report_time_start( );
3466
if( (size_t) length > SSIZE_MAX || (size_t) length < 0 ) {
3467
report( "RXTXPort:readArray length > SSIZE_MAX" );
3468
LEAVE( "RXTXPort:readArray" );
3469
throw_java_exception( env, ARRAY_INDEX_OUT_OF_BOUNDS,
3470
"readArray", "Invalid length" );
3473
body = (*env)->GetByteArrayElements( env, jbarray, 0 );
3474
terminator = (*env)->GetByteArrayElements( env, jterminator, 0 );
3477
bytes = read_byte_array( env, &jobj, fd, (unsigned char *)(body+offset + total ), 1 , timeout );/* dima */
3480
report( "RXTXPort:readArray bytes < 0" );
3481
LEAVE( "RXTXPort:readArray" );
3482
throw_java_exception( env, IO_EXCEPTION, "readArray",
3483
strerror( errno ) );
3486
if ( total > 1 && terminator[1] == body[total -1] &&
3487
terminator[ 0 ] == body[ total -2 ]
3490
report("Got terminator!\n" );
3494
} while ( bytes > 0 && total < length );
3495
(*env)->ReleaseByteArrayElements( env, jbarray, body, 0 );
3497
sprintf( msg, "RXTXPort:readArray: %i %i\n", (int) length, bytes);
3500
LEAVE( "RXTXPort:readArray" );
3132
3502
return (bytes);
3216
3587
if( tcgetattr( fd, &ttyset ) ) goto fail;
3218
3589
if ( flowmode & ( FLOWCONTROL_RTSCTS_IN | FLOWCONTROL_RTSCTS_OUT ) )
3219
3591
ttyset.c_cflag |= HARDWARE_FLOW_CONTROL;
3220
3593
else ttyset.c_cflag &= ~HARDWARE_FLOW_CONTROL;
3222
3595
ttyset.c_iflag &= ~IXANY;
3224
3597
if ( flowmode & FLOWCONTROL_XONXOFF_IN )
3225
3599
ttyset.c_iflag |= IXOFF;
3226
3601
else ttyset.c_iflag &= ~IXOFF;
3228
3603
if ( flowmode & FLOWCONTROL_XONXOFF_OUT )
3229
3606
ttyset.c_iflag |= IXON;
3230
3608
else ttyset.c_iflag &= ~IXON;
3232
3610
if( tcsetattr( fd, TCSANOW, &ttyset ) ) goto fail;
3233
3611
LEAVE( "RXTXPort:setflowcontrol" );
3252
3630
void unlock_monitor_thread( struct event_info_struct *eis )
3254
3632
JNIEnv *env = eis->env;
3633
jobject jobj = *(eis->jobj);
3256
jfieldID jfid = (*env)->GetFieldID( env, eis->jclazz,
3257
"MonitorThreadLock", "Z" );
3258
(*env)->SetBooleanField( env, *eis->jobj, jfid, JNI_FALSE );
3635
jfieldID jfid = (*env)->GetFieldID( env, (*env)->GetObjectClass( env, jobj ), "MonitorThreadLock", "Z" );
3636
(*env)->SetBooleanField( env, jobj, jfid, (jboolean) 0 );
3261
3639
/*----------------------------------------------------------
3710
4088
report_time_eventLoop( );
3712
/* report( "." ); */
3713
eis.ret = SELECT( eis.fd + 1, &eis.rfds, NULL, NULL,
3715
4090
/* nothing goes between this call and select */
3716
4091
if( eis.closing )
3718
4093
report("eventLoop: got interrupt\n");
3719
4094
finalize_threads( &eis );
3720
4095
finalize_event_info_struct( &eis );
3721
(*env)->SetBooleanField( env, jobj,
3723
4096
LEAVE("eventLoop");
4100
/* report( "." ); */
4101
eis.ret = SELECT( eis.fd + 1, &eis.rfds, NULL, NULL,
4105
termios.c:serial_select is instable for some
4108
polling is not blowing up.
3728
Trent system_wait();
4116
if(eis.eventflags[SPE_DATA_AVAILABLE] )
4118
if( port_has_changed_fionread( &eis ) )
4120
send_event( &eis, SPE_DATA_AVAILABLE, 1 );
3730
4127
} while ( eis.ret < 0 && errno == EINTR );
3731
4128
if( eis.ret >= 0 )
3787
4185
/* We opened the file in this thread, use this pid to unlock */
3789
4187
pid = getpid();
4189
char full_windows_name[80];
3790
4190
#endif /* WIN32 */
3792
4192
ENTER( "RXTXPort:testRead" );
3793
4193
#ifdef TRENT_IS_HERE_DEBUGGING_ENUMERATION
3794
4194
/* vmware lies about which ports are there causing irq conflicts */
3795
4195
/* this is for testing only */
3796
if( !strcmp( name, "COM1" ) )
4196
if( !strcmp( name, "COM1" ) || !strcmp( name, "COM2") )
4198
printf("%s is good\n",name);
3798
4199
sprintf( message, "testRead: %s is good!\n", name );
3799
4200
report( message );
3800
4201
(*env)->ReleaseStringUTFChars( env, tty_name, name );
4696
5099
#endif /* LFS */
4698
5101
/*----------------------------------------------------------
5104
accept: The name of the device to try to unlock
5105
perform: Remove a lock file if there is one using a
5107
return: 1 on failure 0 on success
5109
comments: This is for use with liblockdev which comes with Linux
5110
distros. I suspect it will be problematic with embeded
5113
----------------------------------------------------------*/
5115
int lib_lock_dev_unlock( const char *filename, int pid )
5117
if( dev_unlock( filename, pid ) )
5119
report("fhs_unlock: Unable to remove LockFile\n");
5124
#endif /* LIBLOCKDEV */
5126
/*----------------------------------------------------------
5129
accept: The name of the device to try to lock
5131
perform: Create a lock file if there is not one already.
5132
return: 1 on failure 0 on success
5134
comments: This is for use with liblockdev which comes with Linux
5135
distros. I suspect it will be problematic with embeded
5138
One could load the library here rather than link it and
5139
always try to use this.
5141
----------------------------------------------------------*/
5143
int lib_lock_dev_lock( const char *filename, int pid )
5146
printf("LOCKING %s\n", filename);
5147
if ( dev_testlock( filename ) )
5149
report( "fhs_lock() lockstatus fail\n" );
5152
if ( dev_lock( filename ) )
5155
"RXTX fhs_lock() Error: creating lock file for: %s: %s\n",
5156
filename, strerror(errno) );
5157
report_error( message );
5162
#endif /* LIBLOCKDEV */
5164
/*----------------------------------------------------------
4701
5167
accept: The name of the device to try to lock
5390
5858
fprintf(stderr,"\n" );
5391
5859
#endif /* DEBUG */
5862
/*----------------------------------------------------------
5863
get_java_environment
5865
accept: pointer to the virtual machine
5866
flag to know if we are attached
5867
return: pointer to the Java Environment
5869
comments: see JNI_OnLoad. For getting the JNIEnv in the thread
5870
used to monitor for output buffer empty.
5871
----------------------------------------------------------*/
5872
JNIEnv *get_java_environment(JavaVM *java_vm, jboolean *was_attached){
5875
if(java_vm == NULL) return (JNIEnv *) *env;
5876
*was_attached = JNI_FALSE;
5878
err_get_env = (*java_vm)->GetEnv(
5883
if(err_get_env == JNI_ERR) return NULL;
5884
if(err_get_env == JNI_EDETACHED){
5885
(*java_vm)->AttachCurrentThread(
5890
if(*env != NULL) *was_attached = JNI_TRUE;
5891
}else if(err_get_env != JNI_OK) return (JNIEnv *) NULL;
5892
return (JNIEnv *) *env;
5895
/*----------------------------------------------------------
5898
accept: JavaVM pointer to the Vertial Machine
5900
return: jint JNI version used.
5902
comments: http://java.sun.com/j2se/1.4.2/docs/guide/jni/jni-14.html
5903
http://java.sun.com/j2se/1.4.2/docs/guide/jni/jni-12.html
5904
grab the Java VM pointer when the library loads for later use
5905
in the drain thread. Also lets Java know we are using the
5906
1.4 API so we can get pointers later.
5907
----------------------------------------------------------*/
5908
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *java_vm, void *reserved)
5911
printf("Experimental: JNI_OnLoad called.\n");
5912
return JNI_VERSION_1_2; /* JNI API used */
5915
/*----------------------------------------------------------
5918
accept: JavaVM pointer to the Vertial Machine
5922
comments: http://java.sun.com/j2se/1.4.2/docs/guide/jni/jni-14.html
5923
http://java.sun.com/j2se/1.4.2/docs/guide/jni/jni-12.html
5924
final library cleanup here.
5925
----------------------------------------------------------*/
5926
JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *vm, void *reserved)
5928
/* never called it appears */
5929
printf("Experimental: JNI_OnUnload called.\n");
5933
/*----------------------------------------------------------
5936
accept: like vwprintf()
5937
return: number of jchars written or -1
5939
comments: prints data using System.out.print()
5940
----------------------------------------------------------*/
5941
int printj(JNIEnv *env, wchar_t *fmt, ...)
5946
jclass clsSystem, clsOut;
5953
retval = _vsnwprintf(buf, 1024, fmt, ap);
5957
if((clsSystem = env->FindClass("java/lang/System")) == NULL)
5961
env->ExceptionDescribe();
5963
env->ExceptionClear();
5967
if( ( jfid = env->GetStaticFieldID(clsSystem,
5968
"out", "Ljava/io/PrintStream;" ) ) == NULL )
5972
env->ExceptionDescribe();
5974
env->ExceptionClear();
5975
env->DeleteLocalRef(clsSystem);
5979
objOut = env->GetStaticObjectField(clsSystem, jfid);
5980
clsOut = env->GetObjectClass(objOut);
5982
if( ( midPrint = env->GetMethodID(clsOut, "print",
5983
"(Ljava/lang/String;)V" ) ) == NULL )
5987
env->ExceptionDescribe();
5989
env->ExceptionClear();
5990
env->DeleteLocalRef(clsOut);
5991
env->DeleteLocalRef(clsSystem);
5995
jsBuf = env->NewString(buf, wcslen(buf));
5997
env->CallVoidMethod(objOut, midPrint, jsBuf);
5999
env->DeleteLocalRef(jsBuf);
6000
env->DeleteLocalRef(clsOut);
6001
env->DeleteLocalRef(clsSystem);
6006
jclass cls = ( *env )->FindClass( env, "System.Thread" );
6007
jmethodID mid = ( *env )->GetStaticMethodID( env, cls, "Sleep", "(I)V" );
6008
(*env)->CallStaticVoidMethod(env, cls, mid, 1);