Skip to content

Commit 260e61b

Browse files
committed
[jnienv-gen] Generate a header file for the native functions
In addition to generating a .c file, generate a .h one with declarations of all the functions defined 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 260e61b

File tree

1 file changed

+100
-49
lines changed

1 file changed

+100
-49
lines changed

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
partial class Generator
1717
{
1818
static string jnienv_g_c;
19+
static string jnienv_g_h;
1920
static string jnienv_g_cs;
2021

2122
public static int Main (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.ChangeExtension (jnienv_g_c, ".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 (TextWriter w = new StringWriter ()) {
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 (TextWriter w = new StringWriter ()) {
40-
w.NewLine = "\n";
41-
GenerateNativeLibSource (w);
42-
string content = 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 (TextWriter sw = new StringWriter ()) {
52+
using (TextWriter hw = new StringWriter ()) {
53+
sw.NewLine = "\n";
54+
GenerateNativeLibSource (sw, hw, jnienv_g_h);
55+
string sourceContent = sw.ToString ();
56+
string headerContent = 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
return 0;
4967
} catch (Exception ex) {
5068
Console.WriteLine (ex);
@@ -431,67 +449,100 @@ static void RaiseException (TextWriter o, JniFunction entry, HandleStyle style)
431449
o.WriteLine ();
432450
}
433451

434-
static void GenerateNativeLibSource (TextWriter o)
452+
static void WriteNativeFileHeader (TextWriter o)
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+
static void GenerateNativeLibSource (TextWriter source, TextWriter header, string headerName)
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 \"{headerName}\"");
504+
}
505+
468506
foreach (JniFunction entry in JNIEnvEntries) {
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
bool isVoid = 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)