@@ -962,8 +962,9 @@ get_conversion_flag(JNIEnv* env, jclass cls) {
962
962
int
963
963
get_java_type_from_ffi_type (ffi_type * type ) {
964
964
switch (type -> type ) {
965
- // FIXME aliases 'C' on *nix; this will cause problems if anyone
966
- // ever installs a type mapper for char/Character (not a common arg type)
965
+ // NOTE 'Z' aliases 'C' on *nix and platforms where sizeof(wchar_t) is 4;
966
+ // this will cause problems if anyone ever installs a type mapper for
967
+ // char/Character (not a common arg type)
967
968
case FFI_TYPE_UINT32 : return 'Z' ;
968
969
case FFI_TYPE_SINT8 : return 'B' ;
969
970
case FFI_TYPE_SINT16 : return 'S' ;
@@ -1113,11 +1114,11 @@ getFFITypeTypeMapped(JNIEnv* env, jobject converter) {
1113
1114
}
1114
1115
1115
1116
void
1116
- toNative (JNIEnv * env , jobject obj , void * valuep , size_t size , jboolean promote ) {
1117
+ toNative (JNIEnv * env , jobject obj , void * valuep , size_t size , jboolean promote , const char * encoding ) {
1117
1118
if (obj != NULL ) {
1118
1119
jobject arg = (* env )-> CallObjectMethod (env , obj , MID_NativeMapped_toNative );
1119
1120
if (!(* env )-> ExceptionCheck (env )) {
1120
- extract_value (env , arg , valuep , size , promote );
1121
+ extract_value (env , arg , valuep , size , promote , encoding );
1121
1122
}
1122
1123
}
1123
1124
else {
@@ -1126,11 +1127,11 @@ toNative(JNIEnv* env, jobject obj, void* valuep, size_t size, jboolean promote)
1126
1127
}
1127
1128
1128
1129
static void
1129
- toNativeTypeMapped (JNIEnv * env , jobject obj , void * valuep , size_t size , jobject to_native ) {
1130
+ toNativeTypeMapped (JNIEnv * env , jobject obj , void * valuep , size_t size , jobject to_native , const char * encoding ) {
1130
1131
if (obj != NULL ) {
1131
1132
jobject arg = (* env )-> CallStaticObjectMethod (env , classNative , MID_Native_toNativeTypeMapped , to_native , obj );
1132
1133
if (!(* env )-> ExceptionCheck (env )) {
1133
- extract_value (env , arg , valuep , size , JNI_FALSE );
1134
+ extract_value (env , arg , valuep , size , JNI_FALSE , encoding );
1134
1135
}
1135
1136
}
1136
1137
else {
@@ -1141,11 +1142,11 @@ toNativeTypeMapped(JNIEnv* env, jobject obj, void* valuep, size_t size, jobject
1141
1142
static void
1142
1143
fromNativeTypeMapped (JNIEnv * env , jobject from_native ,
1143
1144
void * native_return_value ,
1144
- ffi_type * native_return_type ,
1145
+ int jtype , int size ,
1145
1146
jclass java_return_class ,
1146
- void * result_storage ) {
1147
- int jtype = get_java_type_from_ffi_type ( native_return_type );
1148
- jobject value = new_object (env , (char )jtype , native_return_value , JNI_TRUE );
1147
+ void * result_storage ,
1148
+ const char * encoding ) {
1149
+ jobject value = new_object (env , (char )jtype , native_return_value , JNI_TRUE , encoding );
1149
1150
if (!(* env )-> ExceptionCheck (env )) {
1150
1151
jobject obj = (* env )-> CallStaticObjectMethod (env , classNative ,
1151
1152
MID_Native_fromNativeTypeMapped ,
@@ -1160,7 +1161,7 @@ fromNativeTypeMapped(JNIEnv* env, jobject from_native,
1160
1161
|| (* env )-> IsSameObject (env , java_return_class , classPrimitiveLong )
1161
1162
|| (* env )-> IsSameObject (env , java_return_class , classPrimitiveFloat )
1162
1163
|| (* env )-> IsSameObject (env , java_return_class , classPrimitiveDouble )) {
1163
- extract_value (env , obj , result_storage , native_return_type -> size , JNI_TRUE );
1164
+ extract_value (env , obj , result_storage , size , JNI_TRUE , encoding );
1164
1165
}
1165
1166
else {
1166
1167
* (jobject * )result_storage = obj ;
@@ -1170,9 +1171,9 @@ fromNativeTypeMapped(JNIEnv* env, jobject from_native,
1170
1171
}
1171
1172
1172
1173
jobject
1173
- fromNative (JNIEnv * env , jclass javaClass , ffi_type * type , void * resp , jboolean promote ) {
1174
+ fromNative (JNIEnv * env , jclass javaClass , ffi_type * type , void * resp , jboolean promote , const char * encoding ) {
1174
1175
int jtype = get_java_type_from_ffi_type (type );
1175
- jobject value = new_object (env , (char )jtype , resp , promote );
1176
+ jobject value = new_object (env , (char )jtype , resp , promote , encoding );
1176
1177
if (!(* env )-> ExceptionCheck (env )) {
1177
1178
return (* env )-> CallStaticObjectMethod (env , classNative ,
1178
1179
MID_Native_fromNative ,
@@ -1455,9 +1456,12 @@ JNA_init(JNIEnv* env) {
1455
1456
return NULL ;
1456
1457
}
1457
1458
1458
- /** Copy value from the given Java object into the given storage buffer. */
1459
+ /** Copy value from the given Java object into the given storage buffer.
1460
+ * If the value is being extracted from a String or WString, you are
1461
+ * responsible for freeing the allocated memory.
1462
+ */
1459
1463
void
1460
- extract_value (JNIEnv * env , jobject value , void * buffer , size_t size , jboolean promote ) {
1464
+ extract_value (JNIEnv * env , jobject value , void * buffer , size_t size , jboolean promote , const char * encoding ) {
1461
1465
if (value == NULL ) {
1462
1466
* (void * * )buffer = NULL ;
1463
1467
}
@@ -1525,19 +1529,32 @@ extract_value(JNIEnv* env, jobject value, void* buffer, size_t size, jboolean pr
1525
1529
else if ((* env )-> IsInstanceOf (env , value , classPointer )) {
1526
1530
* (void * * )buffer = getNativeAddress (env , value );
1527
1531
}
1532
+ else if ((* env )-> IsInstanceOf (env , value , classString )) {
1533
+ * (void * * )buffer = newCStringEncoding (env , (jstring )value , encoding );
1534
+ }
1535
+ else if ((* env )-> IsInstanceOf (env , value , classWString )) {
1536
+ jstring s = (* env )-> CallObjectMethod (env , value , MID_Object_toString );
1537
+ * (void * * )buffer = newWideCString (env , s );
1538
+ }
1528
1539
else {
1529
- fprintf (stderr , "JNA: extract_value: unrecognized return type, size %d\n" , (int )size );
1540
+ char msg [MSG_SIZE ];
1541
+ snprintf (msg , sizeof (msg ), "Can't convert type to native, native size %d\n" , (int )size );
1542
+ fprintf (stderr , "JNA: extract_value: %s" , msg );
1530
1543
memset (buffer , 0 , size );
1531
- throwByName (env , EError , "Unrecognized return type" );
1544
+ throwByName (env , EError , msg );
1532
1545
}
1533
1546
}
1534
1547
1535
1548
/** Construct a new Java object from a native value. */
1536
1549
jobject
1537
- new_object (JNIEnv * env , char jtype , void * valuep , jboolean promote ) {
1550
+ new_object (JNIEnv * env , char jtype , void * valuep , jboolean promote , const char * encoding ) {
1538
1551
switch (jtype ) {
1539
1552
case 's' :
1540
1553
return newJavaPointer (env , valuep );
1554
+ case 'c' :
1555
+ return newJavaString (env , * (void * * )valuep , encoding );
1556
+ case 'w' :
1557
+ return newJavaString (env , * (void * * )valuep , NULL );
1541
1558
case '*' :
1542
1559
return newJavaPointer (env , * (void * * )valuep );
1543
1560
case 'J' :
@@ -1613,6 +1630,8 @@ get_ffi_type(JNIEnv* env, jclass cls, char jtype) {
1613
1630
return NULL ;
1614
1631
}
1615
1632
case '*' :
1633
+ case 'c' :
1634
+ case 'w' :
1616
1635
default :
1617
1636
return & ffi_type_pointer ;
1618
1637
}
@@ -1706,22 +1725,27 @@ dispatch_direct(ffi_cif* cif, void* volatile resp, void** argp, void *cdata) {
1706
1725
* (void * * )args [i ] = getPointerTypeAddress (env , * (void * * )args [i ]);
1707
1726
break ;
1708
1727
case CVT_TYPE_MAPPER :
1728
+ case CVT_TYPE_MAPPER_STRING :
1729
+ case CVT_TYPE_MAPPER_WSTRING :
1709
1730
{
1710
1731
void * valuep = args [i ];
1711
1732
int jtype = get_java_type_from_ffi_type (data -> closure_cif .arg_types [i + 2 ]);
1712
1733
jobject obj = jtype == '*'
1713
1734
? * (void * * )valuep
1714
- : new_object (env , (char )jtype , valuep , JNI_FALSE );
1735
+ : new_object (env , (char )jtype , valuep , JNI_FALSE , data -> encoding );
1715
1736
if (cif -> arg_types [i + 2 ]-> size < data -> cif .arg_types [i ]-> size ) {
1716
1737
args [i ] = alloca (data -> cif .arg_types [i ]-> size );
1717
1738
}
1718
1739
toNativeTypeMapped (env , obj , args [i ],
1719
1740
data -> cif .arg_types [i ]-> size ,
1720
- data -> to_native [i ]);
1741
+ data -> to_native [i ],
1742
+ data -> encoding );
1721
1743
}
1722
1744
break ;
1723
1745
case CVT_NATIVE_MAPPED :
1724
- toNative (env , * (void * * )args [i ], args [i ], data -> cif .arg_types [i ]-> size , JNI_FALSE );
1746
+ case CVT_NATIVE_MAPPED_STRING :
1747
+ case CVT_NATIVE_MAPPED_WSTRING :
1748
+ toNative (env , * (void * * )args [i ], args [i ], data -> cif .arg_types [i ]-> size , JNI_FALSE , data -> encoding );
1725
1749
break ;
1726
1750
case CVT_POINTER :
1727
1751
* (void * * )args [i ] = getNativeAddress (env , * (void * * )args [i ]);
@@ -1825,12 +1849,22 @@ dispatch_direct(ffi_cif* cif, void* volatile resp, void** argp, void *cdata) {
1825
1849
1826
1850
switch (data -> rflag ) {
1827
1851
case CVT_TYPE_MAPPER :
1828
- fromNativeTypeMapped (env , data -> from_native , resp , data -> cif .rtype , data -> closure_rclass , oldresp );
1852
+ case CVT_TYPE_MAPPER_STRING :
1853
+ case CVT_TYPE_MAPPER_WSTRING :
1854
+ {
1855
+ int jtype = (data -> rflag == CVT_TYPE_MAPPER_STRING
1856
+ ? 'c' : (data -> rflag == CVT_TYPE_MAPPER_WSTRING
1857
+ ? 'w' : get_java_type_from_ffi_type (data -> cif .rtype )));
1858
+ fromNativeTypeMapped (env , data -> from_native , resp , jtype , data -> cif .rtype -> size ,
1859
+ data -> closure_rclass , oldresp , data -> encoding );
1860
+ }
1829
1861
break ;
1830
1862
case CVT_INTEGER_TYPE :
1831
1863
case CVT_POINTER_TYPE :
1832
1864
case CVT_NATIVE_MAPPED :
1833
- * (void * * )oldresp = fromNative (env , data -> closure_rclass , data -> cif .rtype , resp , JNI_TRUE );
1865
+ case CVT_NATIVE_MAPPED_STRING :
1866
+ case CVT_NATIVE_MAPPED_WSTRING :
1867
+ * (void * * )oldresp = fromNative (env , data -> closure_rclass , data -> cif .rtype , resp , JNI_TRUE , data -> encoding );
1834
1868
break ;
1835
1869
case CVT_POINTER :
1836
1870
* (void * * )resp = newJavaPointer (env , * (void * * )resp );
@@ -1865,6 +1899,10 @@ dispatch_direct(ffi_cif* cif, void* volatile resp, void** argp, void *cdata) {
1865
1899
break ;
1866
1900
case CVT_STRING :
1867
1901
case CVT_WSTRING :
1902
+ case CVT_TYPE_MAPPER_STRING :
1903
+ case CVT_TYPE_MAPPER_WSTRING :
1904
+ case CVT_NATIVE_MAPPED_STRING :
1905
+ case CVT_NATIVE_MAPPED_WSTRING :
1868
1906
// Free allocated native strings
1869
1907
free (* (void * * )args [i ]);
1870
1908
break ;
@@ -3281,7 +3319,9 @@ Java_com_sun_jna_Native_registerMethod(JNIEnv *env, jclass UNUSED(ncls),
3281
3319
if (cvts ) {
3282
3320
data -> flags [i ] = cvts [i ];
3283
3321
// Type mappers only apply to non-primitive arguments
3284
- if (cvts [i ] == CVT_TYPE_MAPPER ) {
3322
+ if (cvts [i ] == CVT_TYPE_MAPPER
3323
+ || cvts [i ] == CVT_TYPE_MAPPER_STRING
3324
+ || cvts [i ] == CVT_TYPE_MAPPER_WSTRING ) {
3285
3325
if (!data -> to_native ) {
3286
3326
data -> to_native = calloc (argc , sizeof (jweak ));
3287
3327
}
0 commit comments