Skip to content
This repository was archived by the owner on Jul 6, 2026. It is now read-only.

Commit cd4c8f8

Browse files
authored
[jnienv-gen] Generate a header file for the native functions (#809)
Update `jnienv-gen` so that in addition to generate `.c` and `.cs` files, it also generates a `.h` file with declarations for the functions in the `.c` file. The header will be used by the NET6 build of Xamarin.Android's native runtime. Additionally, make it possible to *not* export symbols by defining the `JI_NO_VISIBILITY` preprocessor macro. This will also be used by the NET6 build of Xamarin.Android native runtime (which will no longer need to make the symbols visible for `p/invoke` to work).
1 parent 69767c1 commit cd4c8f8

1 file changed

Lines changed: 100 additions & 49 deletions

File tree

‎build-tools/jnienv-gen/Generator.cs‎

Lines changed: 100 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,28 @@ public static string FixupType (this string t)
1616
partialclassGenerator
1717
{
1818
staticstringjnienv_g_c;
19+
staticstringjnienv_g_h;
1920
staticstringjnienv_g_cs;
2021

2122
publicstaticintMain(string[]args)
2223
{
2324
jnienv_g_c="JniEnvironment.g.c";
25+
jnienv_g_h="JniEnvironment.g.h";
2426
jnienv_g_cs="JniEnvironment.g.cs";
2527
if(args.Length>0)
2628
jnienv_g_cs=args[0];
27-
if(args.Length>1)
29+
if(args.Length>1){
2830
jnienv_g_c=args[1];
31+
if(jnienv_g_c!="-"){
32+
jnienv_g_h=Path.Combine(Path.GetDirectoryName(jnienv_g_c),$"{Path.GetFileNameWithoutExtension(jnienv_g_c)}-api.h");
33+
}else{
34+
jnienv_g_h="-";
35+
}
36+
}
37+
if(args.Length>2){
38+
jnienv_g_h=args[2];
39+
}
40+
2941
try{
3042
using(TextWriterw=newStringWriter()){
3143
w.NewLine="\n";
@@ -36,15 +48,21 @@ public static int Main (string [] args)
3648
else
3749
File.WriteAllText(jnienv_g_cs,content);
3850
}
39-
using(TextWriterw=newStringWriter()){
40-
w.NewLine="\n";
41-
GenerateNativeLibSource(w);
42-
stringcontent=w.ToString();
43-
if(jnienv_g_c=="-"||jnienv_g_cs=="-")
44-
Console.WriteLine(content);
45-
else
46-
File.WriteAllText(jnienv_g_c,content);
47-
}
51+
using(TextWritersw=newStringWriter()){
52+
using(TextWriterhw=newStringWriter()){
53+
sw.NewLine="\n";
54+
GenerateNativeLibSource(sw,hw,jnienv_g_h);
55+
stringsourceContent=sw.ToString();
56+
stringheaderContent=hw.ToString();
57+
if(jnienv_g_c=="-"||jnienv_g_cs=="-"){
58+
Console.WriteLine(headerContent);
59+
Console.WriteLine();
60+
Console.WriteLine(sourceContent);
61+
}else{
62+
File.WriteAllText(jnienv_g_h,headerContent);
63+
File.WriteAllText(jnienv_g_c,sourceContent);
64+
}
65+
}}
4866
return0;
4967
}catch(Exceptionex){
5068
Console.WriteLine(ex);
@@ -431,67 +449,100 @@ static void RaiseException (TextWriter o, JniFunction entry, HandleStyle style)
431449
o.WriteLine();
432450
}
433451

434-
staticvoidGenerateNativeLibSource(TextWritero)
452+
staticvoidWriteNativeFileHeader(TextWritero)
435453
{
436454
o.WriteLine("/*");
437455
o.WriteLine(" * Generated file; DO NOT EDIT!");
438456
o.WriteLine(" *");
439-
o.WriteLine(" * To make changes, edit Java.Interop/tools/jnienv-gen and rerun");
457+
o.WriteLine(" * To make changes, edit Java.Interop/build-tools/jnienv-gen and rerun");
440458
o.WriteLine(" */");
441459
o.WriteLine();
442-
o.WriteLine("#include <jni.h>");
443-
o.WriteLine();
444-
o.WriteLine("typedef jmethodID jstaticmethodID;");
445-
o.WriteLine("typedef jfieldID jstaticfieldID;");
446-
o.WriteLine("typedef jobject jglobal;");
447-
o.WriteLine();
448-
o.WriteLine("/* VS 2010 and later have stdint.h */");
449-
o.WriteLine("#if defined(_MSC_VER)");
450-
o.WriteLine();
451-
o.WriteLine(" #define JI_API_EXPORT __declspec(dllexport)");
452-
o.WriteLine(" #define JI_API_IMPORT __declspec(dllimport)");
453-
o.WriteLine();
454-
o.WriteLine("#else /* defined(_MSC_VER */");
455-
o.WriteLine();
456-
o.WriteLine("\t#define JI_API_EXPORT __attribute__ ((visibility (\"default\")))");
457-
o.WriteLine(" #define JI_API_IMPORT");
458-
o.WriteLine();
459-
o.WriteLine("#endif /* !defined(_MSC_VER) */");
460-
o.WriteLine();
461-
o.WriteLine("#if defined(JI_DLL_EXPORT)");
462-
o.WriteLine(" #define JI_API JI_API_EXPORT");
463-
o.WriteLine("#elif defined(JI_DLL_IMPORT)");
464-
o.WriteLine(" #define JI_API JI_API_IMPORT");
465-
o.WriteLine("#else /* !defined(JI_DLL_IMPORT) && !defined(JI_API_IMPORT) */");
466-
o.WriteLine(" #define JI_API");
467-
o.WriteLine("#endif /* JI_DLL_EXPORT... */");
460+
}
461+
462+
staticvoidGenerateNativeLibSource(TextWritersource,TextWriterheader,stringheaderName)
463+
{
464+
WriteNativeFileHeader(source);
465+
WriteNativeFileHeader(header);
466+
467+
header.WriteLine("#if !defined (__JAVA_INTEROP_NATIVE_H)");
468+
header.WriteLine("#define __JAVA_INTEROP_NATIVE_H");
469+
header.WriteLine();
470+
header.WriteLine("#include <jni.h>");
471+
header.WriteLine();
472+
header.WriteLine("typedef jmethodID jstaticmethodID;");
473+
header.WriteLine("typedef jfieldID jstaticfieldID;");
474+
header.WriteLine("typedef jobject jglobal;");
475+
header.WriteLine();
476+
header.WriteLine("#if !defined(JI_NO_VISIBILITY)");
477+
header.WriteLine("\t/* VS 2010 and later have stdint.h */");
478+
header.WriteLine("\t#if defined(_MSC_VER)");
479+
header.WriteLine();
480+
header.WriteLine("\t\t#define JI_API_EXPORT __declspec(dllexport)");
481+
header.WriteLine("\t\t#define JI_API_IMPORT __declspec(dllimport)");
482+
header.WriteLine();
483+
header.WriteLine("\t#else /* defined(_MSC_VER */");
484+
header.WriteLine();
485+
header.WriteLine("\t\t#define JI_API_EXPORT __attribute__ ((visibility (\"default\")))");
486+
header.WriteLine("\t\t#define JI_API_IMPORT");
487+
header.WriteLine();
488+
header.WriteLine("\t#endif /* !defined(_MSC_VER) */");
489+
header.WriteLine();
490+
header.WriteLine("\t#if defined(JI_DLL_EXPORT)");
491+
header.WriteLine("\t\t#define JI_API JI_API_EXPORT");
492+
header.WriteLine("\t#elif defined(JI_DLL_IMPORT)");
493+
header.WriteLine("\t\t#define JI_API JI_API_IMPORT");
494+
header.WriteLine("\t#else /* !defined(JI_DLL_IMPORT) && !defined(JI_API_IMPORT) */");
495+
header.WriteLine("\t\t#define JI_API");
496+
header.WriteLine("\t#endif /* JI_DLL_EXPORT... */");
497+
header.WriteLine("#else // JI_NO_VISIBILITY");
498+
header.WriteLine("\t#define JI_API");
499+
header.WriteLine("#endif // JI_NO_VISIBILITY");
500+
header.WriteLine();
501+
502+
if(headerName!="-"){
503+
source.WriteLine($"#include \"{Path.GetFileName(headerName)}\"");
504+
}
505+
468506
foreach(JniFunctionentryinJNIEnvEntries){
469507
if(entry.IsPrivate||entry.CustomWrapper)
470508
continue;
471-
o.WriteLine();
472-
o.WriteLine("JI_API {0}",entry.ReturnType.JniType);
473-
o.WriteLine("{0} (JNIEnv *env{1}{2}{3})",
509+
510+
header.WriteLine(
511+
"JI_API {0} {1} (JNIEnv *env{2}{3}{4});",
512+
entry.ReturnType.JniType,
513+
GetPinvokeName(entry.Name),
514+
entry.Throws?", jthrowable *_thrown":"",
515+
entry.Parameters.Length!=0?", ":"",
516+
string.Join(", ",entry.Parameters.Select(p =>string.Format("{0} {1}",p.Type.JniType,p.Name)))
517+
);
518+
519+
source.WriteLine();
520+
source.WriteLine("JI_API {0}",entry.ReturnType.JniType);
521+
source.WriteLine("{0} (JNIEnv *env{1}{2}{3})",
474522
GetPinvokeName(entry.Name),
475523
entry.Throws?", jthrowable *_thrown":"",
476524
entry.Parameters.Length!=0?", ":"",
477525
string.Join(", ",entry.Parameters.Select(p =>string.Format("{0} {1}",p.Type.JniType,p.Name))));
478-
o.WriteLine("{");
526+
source.WriteLine("{");
479527
boolisVoid=entry.ReturnType.JniType=="void";
480528
if(entry.Throws)
481-
o.WriteLine("\t*_thrown = 0;");
482-
o.Write("\t");
529+
source.WriteLine("\t*_thrown = 0;");
530+
source.Write("\t");
483531
if(!isVoid)
484-
o.Write("{0} _r_ = ",entry.ReturnType.JniType);
485-
o.WriteLine("(*env)->{0} (env{1}{2});",
532+
source.Write("{0} _r_ = ",entry.ReturnType.JniType);
533+
source.WriteLine("(*env)->{0} (env{1}{2});",
486534
entry.Name,
487535
entry.Parameters.Length!=0?", ":"",
488536
string.Join(", ",entry.Parameters.Select(p =>p.Name)));
489537
if(entry.Throws)
490-
o.WriteLine("\t*_thrown = (*env)->ExceptionOccurred (env);");
538+
source.WriteLine("\t*_thrown = (*env)->ExceptionOccurred (env);");
491539
if(!isVoid)
492-
o.WriteLine("\treturn _r_;");
493-
o.WriteLine("}");
540+
source.WriteLine("\treturn _r_;");
541+
source.WriteLine("}");
494542
}
543+
544+
header.WriteLine();
545+
header.WriteLine("#endif // __JAVA_INTEROP_NATIVE_H");
495546
}
496547
}
497548

0 commit comments

Comments
 (0)