@@ -111,13 +111,13 @@ static void GenerateFile (TextWriter o)
111111 o . WriteLine ( ) ;
112112 o . WriteLine ( "using JNIEnvPtr = System.IntPtr;" ) ;
113113 o . WriteLine ( ) ;
114- o . WriteLine ( "#if FEATURE_JNIENVIRONMENT_JI_INTPTRS || FEATURE_JNIENVIRONMENT_JI_PINVOKES" ) ;
114+ o . WriteLine ( "#if FEATURE_JNIENVIRONMENT_JI_INTPTRS || FEATURE_JNIENVIRONMENT_JI_PINVOKES || FEATURE_JNIENVIRONMENT_JI_FUNCTION_POINTERS " ) ;
115115 o . WriteLine ( "\t using jinstanceFieldID = System.IntPtr;" ) ;
116116 o . WriteLine ( "\t using jstaticFieldID = System.IntPtr;" ) ;
117117 o . WriteLine ( "\t using jinstanceMethodID = System.IntPtr;" ) ;
118118 o . WriteLine ( "\t using jstaticMethodID = System.IntPtr;" ) ;
119119 o . WriteLine ( "\t using jobject = System.IntPtr;" ) ;
120- o . WriteLine ( "#endif // FEATURE_JNIENVIRONMENT_JI_INTPTRS || FEATURE_JNIENVIRONMENT_JI_PINVOKES" ) ;
120+ o . WriteLine ( "#endif // FEATURE_JNIENVIRONMENT_JI_INTPTRS || FEATURE_JNIENVIRONMENT_JI_PINVOKES || FEATURE_JNIENVIRONMENT_JI_FUNCTION_POINTERS " ) ;
121121 o . WriteLine ( ) ;
122122 o . WriteLine ( "namespace Java.Interop {" ) ;
123123 GenerateJniNativeInterface ( o ) ;
@@ -126,6 +126,7 @@ static void GenerateFile (TextWriter o)
126126 WriteSection ( o , HandleStyle . JIIntPtr , "FEATURE_JNIENVIRONMENT_JI_INTPTRS" , "Java.Interop.JIIntPtrs" ) ;
127127 WriteSection ( o , HandleStyle . JIIntPtrPinvokeWithErrors , "FEATURE_JNIENVIRONMENT_JI_PINVOKES" , "Java.Interop.JIPinvokes" ) ;
128128 WriteSection ( o , HandleStyle . XAIntPtr , "FEATURE_JNIENVIRONMENT_XA_INTPTRS" , "Java.Interop.XAIntPtrs" ) ;
129+ WriteSection ( o , HandleStyle . JIFunctionPtrWithErrors , "FEATURE_JNIENVIRONMENT_JI_FUNCTION_POINTERS" , "Java.Interop.JIFunctionPointers" ) ;
129130 }
130131
131132 static void WriteSection ( TextWriter o , HandleStyle style , string define , string specificNamespace )
@@ -139,7 +140,7 @@ static void WriteSection (TextWriter o, HandleStyle style, string define, string
139140 o . WriteLine ( "#endif" ) ;
140141 o . WriteLine ( "{" ) ;
141142 o . WriteLine ( ) ;
142- if ( style != HandleStyle . JIIntPtrPinvokeWithErrors ) {
143+ if ( style != HandleStyle . JIIntPtrPinvokeWithErrors && style != HandleStyle . JIFunctionPtrWithErrors ) {
143144 GenerateDelegates ( o , style ) ;
144145 o . WriteLine ( ) ;
145146 }
@@ -166,26 +167,56 @@ static void GenerateDelegates (TextWriter o, HandleStyle style)
166167
167168 static void GenerateJniNativeInterface ( TextWriter o )
168169 {
170+ o . WriteLine ( "#pragma warning disable 0649 // Field is assigned to, and will always have its default value `null`; ignore as it'll be set in native code." ) ;
171+ o . WriteLine ( "#pragma warning disable 0169 // Field never used; ignore since these fields make the structure have the right layout." ) ;
172+ o . WriteLine ( ) ;
173+
169174 o . WriteLine ( "#if FEATURE_JNIENVIRONMENT_SAFEHANDLES || FEATURE_JNIENVIRONMENT_JI_INTPTRS || FEATURE_JNIENVIRONMENT_XA_INTPTRS" ) ;
170175 o . WriteLine ( "\t [StructLayout (LayoutKind.Sequential)]" ) ;
171176 o . WriteLine ( "\t partial struct JniNativeInterfaceStruct {" ) ;
172177 o . WriteLine ( ) ;
173178
174179 int maxName = JNIEnvEntries . Max ( e => e . Name . Length ) ;
175180
176- o . WriteLine ( "#pragma warning disable 0649 // Field is assigned to, and will always have its default value `null`; ignore as it'll be set in native code." ) ;
177- o . WriteLine ( "#pragma warning disable 0169 // Field never used; ignore since these fields make the structure have the right layout." ) ;
178-
179181 for ( int i = 0 ; i < 4 ; i ++ )
180182 o . WriteLine ( "\t \t private IntPtr reserved{0}; // void*" , i ) ;
181183
182184 foreach ( var e in JNIEnvEntries ) {
183185 o . WriteLine ( "\t \t public IntPtr {0};{1} // {2}" , e . Name , new string ( ' ' , maxName - e . Name . Length ) , e . Prototype ) ;
184186 }
185- o . WriteLine ( "#pragma warning restore 0169" ) ;
186- o . WriteLine ( "#pragma warning restore 0649" ) ;
187187 o . WriteLine ( "\t }" ) ;
188188 o . WriteLine ( "#endif // FEATURE_JNIENVIRONMENT_SAFEHANDLES || FEATURE_JNIENVIRONMENT_JI_INTPTRS || FEATURE_JNIENVIRONMENT_XA_INTPTRS" ) ;
189+ o . WriteLine ( ) ;
190+
191+ o . WriteLine ( "#if FEATURE_JNIENVIRONMENT_JI_FUNCTION_POINTERS" ) ;
192+ o . WriteLine ( "\t [StructLayout (LayoutKind.Sequential)]" ) ;
193+ o . WriteLine ( "\t unsafe partial struct JNIEnv {" ) ;
194+
195+ for ( int i = 0 ; i < 4 ; i ++ )
196+ o . WriteLine ( "\t \t private IntPtr reserved{0}; // void*" , i ) ;
197+
198+ foreach ( var e in JNIEnvEntries ) {
199+ if ( e . Parameters . Length > 0 &&
200+ "va_list" == e . Parameters [ e . Parameters . Length - 1 ] . Type . GetManagedType ( HandleStyle . JIFunctionPtrWithErrors , isReturn : false , isPinvoke : true ) ) {
201+ o . WriteLine ( "\t \t public IntPtr {0};{1} // {2}" , e . Name , new string ( ' ' , maxName - e . Name . Length ) , e . Prototype ) ;
202+ continue ;
203+ }
204+ o . Write ( "\t \t public delegate* unmanaged <IntPtr /* env */" ) ;
205+ foreach ( var p in e . Parameters ) {
206+ o . Write ( ", " ) ;
207+ o . Write ( p . Type . GetMarshalType ( HandleStyle . JIFunctionPtrWithErrors , isReturn : false , isPinvoke : true ) ) ;
208+ o . Write ( $ " /* { p . Name } */") ;
209+ }
210+ o . Write ( ", " ) ;
211+ o . Write ( e . ReturnType . GetMarshalType ( HandleStyle . JIFunctionPtrWithErrors , isReturn : true , isPinvoke : true ) ) ;
212+ o . WriteLine ( $ "> { e . Name } ;") ;
213+ }
214+ o . WriteLine ( "\t }" ) ;
215+ o . WriteLine ( "#endif // FEATURE_JNIENVIRONMENT_JI_FUNCTION_POINTERS" ) ;
216+
217+ o . WriteLine ( ) ;
218+ o . WriteLine ( "#pragma warning restore 0169" ) ;
219+ o . WriteLine ( "#pragma warning restore 0649" ) ;
189220 }
190221
191222 static string Initialize ( JniFunction e , string prefix , string delegateType )
@@ -379,9 +410,12 @@ static void GenerateJniEnv (TextWriter o, string type, string visibility, Handle
379410 o . WriteLine ( ")" ) ;
380411 o . WriteLine ( "\t \t {" ) ;
381412 NullCheckParameters ( o , entry . Parameters , style ) ;
413+ PrepareParameters ( o , entry . Parameters , style ) ;
382414 if ( style == HandleStyle . JIIntPtrPinvokeWithErrors ) {
383415 if ( entry . Throws )
384416 o . WriteLine ( "\t \t \t IntPtr thrown;" ) ;
417+ } else if ( style == HandleStyle . JIFunctionPtrWithErrors ) {
418+ o . WriteLine ( $ "\t \t \t IntPtr __env = JniEnvironment.EnvironmentPointer;") ;
385419 } else {
386420 o . WriteLine ( "\t \t \t var __info = JniEnvironment.CurrentInfo;" ) ;
387421 }
@@ -392,17 +426,27 @@ static void GenerateJniEnv (TextWriter o, string type, string visibility, Handle
392426 o . Write ( "NativeMethods.{0} (JniEnvironment.EnvironmentPointer{1}" ,
393427 GetPinvokeName ( entry . Name ) ,
394428 entry . Throws ? ", out thrown" : "" ) ;
429+ } else if ( style == HandleStyle . JIFunctionPtrWithErrors ) {
430+ o . Write ( $ "(*((JNIEnv**)__env))->{ entry . Name } (__env") ;
395431 } else {
396432 o . Write ( "__info.Invoker.{0} (__info.EnvironmentPointer" , entry . Name ) ;
397433 }
398434 for ( int i = 0 ; i < entry . Parameters . Length ; i ++ ) {
399435 var p = entry . Parameters [ i ] ;
400436 o . Write ( ", " ) ;
401- if ( p . Type . GetManagedType ( style , isReturn : false ) . StartsWith ( "out " , StringComparison . Ordinal ) )
437+ var needOut = p . Type . GetManagedType ( style , isReturn : false ) . StartsWith ( "out " , StringComparison . Ordinal ) ;
438+ if ( needOut && style == HandleStyle . JIFunctionPtrWithErrors ) {
439+ o . Write ( "&" ) ;
440+ } else if ( needOut ) {
402441 o . Write ( "out " ) ;
442+ }
403443 o . Write ( p . Type . GetManagedToMarshalExpression ( style , Escape ( entry . Parameters [ i ] . Name ) ) ) ;
404444 }
405445 o . WriteLine ( ");" ) ;
446+ if ( style == HandleStyle . JIFunctionPtrWithErrors && entry . Throws ) {
447+ o . WriteLine ( "\t \t \t IntPtr thrown = (*((JNIEnv**)__env))->ExceptionOccurred (__env);" ) ;
448+ }
449+ CleanupParameters ( o , entry . Parameters , style ) ;
406450 RaiseException ( o , entry , style ) ;
407451 if ( is_void ) {
408452 } else {
@@ -436,14 +480,38 @@ static void NullCheckParameters (TextWriter o, ParamInfo[] ps, HandleStyle style
436480 o . WriteLine ( ) ;
437481 }
438482
483+ static void PrepareParameters ( TextWriter o , ParamInfo [ ] ps , HandleStyle style )
484+ {
485+ bool haveChecks = false ;
486+ foreach ( var e in ps ) {
487+ foreach ( var s in e . Type . GetManagedToMarshalPrepareStatements ( style , Escape ( e . Name ) ) ) {
488+ haveChecks = true ;
489+ o . WriteLine ( $ "\t \t \t { s } ") ;
490+ }
491+ }
492+ if ( haveChecks )
493+ o . WriteLine ( ) ;
494+ }
495+
496+ static void CleanupParameters ( TextWriter o , ParamInfo [ ] ps , HandleStyle style )
497+ {
498+ foreach ( var e in ps ) {
499+ foreach ( var s in e . Type . GetManagedToMarshalCleanupStatements ( style , Escape ( e . Name ) ) ) {
500+ o . WriteLine ( $ "\t \t \t { s } ") ;
501+ }
502+ }
503+ }
504+
439505 static void RaiseException ( TextWriter o , JniFunction entry , HandleStyle style )
440506 {
441507 if ( ! entry . Throws )
442508 return ;
443509
444510 o . WriteLine ( ) ;
445511 o . WriteLine ( "\t \t \t Exception __e = JniEnvironment.GetExceptionForLastThrowable ({0});" ,
446- style == HandleStyle . JIIntPtrPinvokeWithErrors ? "thrown" : "" ) ;
512+ ( style == HandleStyle . JIIntPtrPinvokeWithErrors || style == HandleStyle . JIFunctionPtrWithErrors )
513+ ? "thrown"
514+ : "" ) ;
447515 o . WriteLine ( "\t \t \t if (__e != null)" ) ;
448516 o . WriteLine ( "\t \t \t \t ExceptionDispatchInfo.Capture (__e).Throw ();" ) ;
449517 o . WriteLine ( ) ;
@@ -728,6 +796,9 @@ public virtual string[] VerifyParameter (HandleStyle style, string variable)
728796 {
729797 return new string [ 0 ] ;
730798 }
799+
800+ public virtual string [ ] GetManagedToMarshalPrepareStatements ( HandleStyle style , string variable ) => Array . Empty < string > ( ) ;
801+ public virtual string [ ] GetManagedToMarshalCleanupStatements ( HandleStyle style , string variable ) => Array . Empty < string > ( ) ;
731802 }
732803
733804 class BuiltinTypeInfo : TypeInfo {
@@ -822,6 +893,9 @@ public StringTypeInfo (string jni)
822893
823894 public override string GetMarshalType ( HandleStyle style , bool isReturn , bool isPinvoke )
824895 {
896+ if ( style == HandleStyle . JIFunctionPtrWithErrors && isPinvoke ) {
897+ return "IntPtr" ;
898+ }
825899 return "string" ;
826900 }
827901
@@ -830,6 +904,16 @@ public override string GetManagedType (HandleStyle style, bool isReturn, bool is
830904 return "string" ;
831905 }
832906
907+ public override string GetManagedToMarshalExpression ( HandleStyle style , string variable )
908+ {
909+ switch ( style ) {
910+ case HandleStyle . JIFunctionPtrWithErrors :
911+ return $ "_{ variable } _ptr";
912+ default :
913+ return variable ;
914+ }
915+ }
916+
833917 public override string [ ] GetMarshalToManagedStatements ( HandleStyle style , string variable , JniFunction entry )
834918 {
835919 switch ( style ) {
@@ -841,6 +925,7 @@ public override string[] GetMarshalToManagedStatements (HandleStyle style, strin
841925 } ;
842926 case HandleStyle . JIIntPtr :
843927 case HandleStyle . JIIntPtrPinvokeWithErrors :
928+ case HandleStyle . JIFunctionPtrWithErrors :
844929 return new [ ] {
845930 string . Format ( "JniEnvironment.LogCreateLocalRef ({0});" , variable ) ,
846931 string . Format ( "return new JniObjectReference ({0}, JniObjectReferenceType.Local);" , variable ) ,
@@ -859,6 +944,30 @@ public override string[] VerifyParameter (HandleStyle style, string variable)
859944 string . Format ( "\t throw new ArgumentNullException (\" {0}\" );" , variableName ) ,
860945 } ;
861946 }
947+
948+ public override string [ ] GetManagedToMarshalPrepareStatements ( HandleStyle style , string variable )
949+ {
950+ switch ( style ) {
951+ case HandleStyle . JIFunctionPtrWithErrors :
952+ return new [ ] {
953+ $ "var _{ variable } _ptr = Marshal.StringToCoTaskMemUTF8 ({ variable } );",
954+ } ;
955+ default :
956+ return base . GetManagedToMarshalPrepareStatements ( style , variable ) ;
957+ }
958+ }
959+
960+ public override string [ ] GetManagedToMarshalCleanupStatements ( HandleStyle style , string variable )
961+ {
962+ switch ( style ) {
963+ case HandleStyle . JIFunctionPtrWithErrors :
964+ return new [ ] {
965+ $ "Marshal.ZeroFreeCoTaskMemUTF8 (_{ variable } _ptr);",
966+ } ;
967+ default :
968+ return base . GetManagedToMarshalCleanupStatements ( style , variable ) ;
969+ }
970+ }
862971 }
863972
864973 class JniReleaseArrayElementsModeTypeInfo : TypeInfo {
@@ -920,6 +1029,7 @@ public override string GetManagedType (HandleStyle style, bool isReturn, bool is
9201029 case HandleStyle . SafeHandle :
9211030 case HandleStyle . JIIntPtr :
9221031 case HandleStyle . JIIntPtrPinvokeWithErrors :
1032+ case HandleStyle . JIFunctionPtrWithErrors :
9231033 return type ;
9241034 case HandleStyle . XAIntPtr :
9251035 return "IntPtr" ;
@@ -933,6 +1043,7 @@ public override string GetManagedToMarshalExpression (HandleStyle style, string
9331043 case HandleStyle . SafeHandle :
9341044 case HandleStyle . JIIntPtr :
9351045 case HandleStyle . JIIntPtrPinvokeWithErrors :
1046+ case HandleStyle . JIFunctionPtrWithErrors :
9361047 return string . Format ( "{0}.ID" , variable ) ;
9371048 }
9381049 return variable ;
@@ -947,6 +1058,7 @@ public override string[] VerifyParameter (HandleStyle style, string variable)
9471058 case HandleStyle . SafeHandle :
9481059 case HandleStyle . JIIntPtr :
9491060 case HandleStyle . JIIntPtrPinvokeWithErrors :
1061+ case HandleStyle . JIFunctionPtrWithErrors :
9501062 return new [ ] {
9511063 string . Format ( "if ({0} == null)" , variable ) ,
9521064 string . Format ( "\t throw new ArgumentNullException (\" {0}\" );" , variableName ) ,
@@ -969,6 +1081,7 @@ public override string[] GetMarshalToManagedStatements (HandleStyle style, strin
9691081 case HandleStyle . SafeHandle :
9701082 case HandleStyle . JIIntPtr :
9711083 case HandleStyle . JIIntPtrPinvokeWithErrors :
1084+ case HandleStyle . JIFunctionPtrWithErrors :
9721085 return new [ ] {
9731086 string . Format ( "if ({0} == IntPtr.Zero)" , variable ) ,
9741087 string . Format ( "\t return null;" ) ,
@@ -1045,6 +1158,7 @@ public override string GetMarshalType (HandleStyle style, bool isReturn, bool is
10451158 return isReturn ? safeType : "JniReferenceSafeHandle" ;
10461159 case HandleStyle . JIIntPtr :
10471160 case HandleStyle . JIIntPtrPinvokeWithErrors :
1161+ case HandleStyle . JIFunctionPtrWithErrors :
10481162 case HandleStyle . XAIntPtr :
10491163 return "jobject" ;
10501164 }
@@ -1057,6 +1171,7 @@ public override string GetManagedType (HandleStyle style, bool isReturn, bool is
10571171 case HandleStyle . SafeHandle :
10581172 case HandleStyle . JIIntPtr :
10591173 case HandleStyle . JIIntPtrPinvokeWithErrors :
1174+ case HandleStyle . JIFunctionPtrWithErrors :
10601175 return "JniObjectReference" ;
10611176 case HandleStyle . XAIntPtr :
10621177 return "IntPtr" ;
@@ -1071,6 +1186,7 @@ public override string GetManagedToMarshalExpression (HandleStyle style, string
10711186 return string . Format ( "{0}.SafeHandle" , variable ) ;
10721187 case HandleStyle . JIIntPtr :
10731188 case HandleStyle . JIIntPtrPinvokeWithErrors :
1189+ case HandleStyle . JIFunctionPtrWithErrors :
10741190 return string . Format ( "{0}.Handle" , variable ) ;
10751191 case HandleStyle . XAIntPtr :
10761192 return variable ;
@@ -1084,6 +1200,7 @@ public override string[] GetMarshalToManagedStatements (HandleStyle style, strin
10841200 case HandleStyle . SafeHandle :
10851201 case HandleStyle . JIIntPtr :
10861202 case HandleStyle . JIIntPtrPinvokeWithErrors :
1203+ case HandleStyle . JIFunctionPtrWithErrors :
10871204 return new [ ] {
10881205 string . Format ( "return new JniObjectReference ({0}, {1});" , variable , refType ) ,
10891206 } ;
@@ -1104,6 +1221,7 @@ public override string[] VerifyParameter (HandleStyle style, string variable)
11041221 case HandleStyle . SafeHandle :
11051222 case HandleStyle . JIIntPtr :
11061223 case HandleStyle . JIIntPtrPinvokeWithErrors :
1224+ case HandleStyle . JIFunctionPtrWithErrors :
11071225 return new [ ] {
11081226 string . Format ( "if (!{0}.IsValid)" , variable ) ,
11091227 string . Format ( "\t throw new ArgumentException (\" Handle must be valid.\" , \" {0}\" );" , variableName ) ,
@@ -1160,13 +1278,50 @@ public JavaVMPointerTypeInfo (string jni)
11601278
11611279 public override string GetMarshalType ( HandleStyle style , bool isReturn , bool isPinvoke )
11621280 {
1281+ if ( style == HandleStyle . JIFunctionPtrWithErrors && isPinvoke ) {
1282+ return "IntPtr*" ;
1283+ }
11631284 return "out IntPtr" ;
11641285 }
11651286
11661287 public override string GetManagedType ( HandleStyle style , bool isReturn , bool isPinvoke )
11671288 {
11681289 return "out IntPtr" ;
11691290 }
1291+
1292+ public override string GetManagedToMarshalExpression ( HandleStyle style , string variable )
1293+ {
1294+ switch ( style ) {
1295+ case HandleStyle . JIFunctionPtrWithErrors :
1296+ return $ "_{ variable } _ptr";
1297+ default :
1298+ return variable ;
1299+ }
1300+ }
1301+
1302+ public override string [ ] GetManagedToMarshalPrepareStatements ( HandleStyle style , string variable )
1303+ {
1304+ switch ( style ) {
1305+ case HandleStyle . JIFunctionPtrWithErrors :
1306+ return new [ ] {
1307+ $ "IntPtr _{ variable } _ptr = IntPtr.Zero;",
1308+ } ;
1309+ default :
1310+ return base . GetManagedToMarshalPrepareStatements ( style , variable ) ;
1311+ }
1312+ }
1313+
1314+ public override string [ ] GetManagedToMarshalCleanupStatements ( HandleStyle style , string variable )
1315+ {
1316+ switch ( style ) {
1317+ case HandleStyle . JIFunctionPtrWithErrors :
1318+ return new [ ] {
1319+ $ "{ variable } = _{ variable } _ptr;",
1320+ } ;
1321+ default :
1322+ return base . GetManagedToMarshalCleanupStatements ( style , variable ) ;
1323+ }
1324+ }
11701325 }
11711326
11721327 class ParamInfo
@@ -1204,6 +1359,7 @@ enum HandleStyle {
12041359 JIIntPtr ,
12051360 JIIntPtrPinvokeWithErrors ,
12061361 XAIntPtr ,
1362+ JIFunctionPtrWithErrors ,
12071363 }
12081364}
12091365
0 commit comments