diff options
24 files changed, 608 insertions, 297 deletions
diff --git a/compiler/build.gradle b/compiler/build.gradle index 11dbb35..d011274 100644 --- a/compiler/build.gradle +++ b/compiler/build.gradle @@ -10,6 +10,7 @@ sourceSets { main { resources { srcDirs += rootProject.file("cpp") +// srcDirs += rootProject.file("templates") } } } @@ -33,4 +34,4 @@ compileTestKotlin { kotlinOptions { jvmTarget = "1.8" } -} +}
\ No newline at end of file diff --git a/compiler/src/main/java/io/github/landerlyoung/jenny/HandyHelper.kt b/compiler/src/main/java/io/github/landerlyoung/jenny/HandyHelper.kt index 7559dbb..575a2f9 100644 --- a/compiler/src/main/java/io/github/landerlyoung/jenny/HandyHelper.kt +++ b/compiler/src/main/java/io/github/landerlyoung/jenny/HandyHelper.kt @@ -282,9 +282,9 @@ class HandyHelper(private val mEnv: Environment) { } - fun getConstructorName(index: Int): String { - return "sConstruct_$index" - } + fun getConstructorName(index: Int) = "sConstruct_$index" + fun getMethodName(e: ExecutableElement, index: Int) = "sMethod_" + e.simpleName + "_" + index + fun getFieldName(e: Element, index: Int) = "sField_" + e.simpleName + "_" + index fun toJNIType(t: TypeMirror?): String { if (t == null) return "" diff --git a/compiler/src/main/java/io/github/landerlyoung/jenny/JteData.kt b/compiler/src/main/java/io/github/landerlyoung/jenny/JteData.kt new file mode 100644 index 0000000..8cf0f5e --- /dev/null +++ b/compiler/src/main/java/io/github/landerlyoung/jenny/JteData.kt @@ -0,0 +1,19 @@ +package io.github.landerlyoung.jenny + +import javax.lang.model.element.TypeElement + +data class JteData( + val className: String, + val simpleClassName: String, + val namespaceHelper: NamespaceHelper, + val slashClassName: String, + val environment: Environment, + var param: String = "", + var returnType: String = "", + var methodPrologue: String = "", + var isStatic: Boolean = false, + var useJniHelper: Boolean = false, + var clazz: TypeElement? = null, + var method: MethodOverloadResolver.MethodRecord? = null, + val handyHelper: HandyHelper +)
\ No newline at end of file diff --git a/compiler/src/main/java/io/github/landerlyoung/jenny/MethodOverloadResolver.kt b/compiler/src/main/java/io/github/landerlyoung/jenny/MethodOverloadResolver.kt index 244f00f..c51299f 100644 --- a/compiler/src/main/java/io/github/landerlyoung/jenny/MethodOverloadResolver.kt +++ b/compiler/src/main/java/io/github/landerlyoung/jenny/MethodOverloadResolver.kt @@ -11,13 +11,14 @@ import javax.lang.model.element.ExecutableElement * ``` */ class MethodOverloadResolver( - private val helper: HandyHelper, - private val nativeParamResolver: (ExecutableElement) -> String + private val helper: HandyHelper, + private val nativeParamResolver: (ExecutableElement) -> String ) { - class MethodRecord( - val method: ExecutableElement, - val resolvedPostFix: String, - val index: Int) + data class MethodRecord( + val method: ExecutableElement, + val resolvedPostFix: String, + val index: Int + ) fun resolve(methodList: List<ExecutableElement>): List<MethodRecord> { val duplicateRecord = mutableMapOf<String, Boolean>() @@ -30,9 +31,9 @@ class MethodOverloadResolver( val p = nativeParamResolver(m) if (duplicateRecord[p]!! || Constants.CPP_RESERVED_WORS.contains(m.simpleName.toString())) { MethodRecord( - m, - helper.getMethodOverloadPostfix(m), - index + m, + helper.getMethodOverloadPostfix(m), + index ) } else { MethodRecord(m, "", index) diff --git a/compiler/src/main/java/io/github/landerlyoung/jenny/NativeProxyGenerator.kt b/compiler/src/main/java/io/github/landerlyoung/jenny/NativeProxyGenerator.kt index 59c9e2e..799051b 100644 --- a/compiler/src/main/java/io/github/landerlyoung/jenny/NativeProxyGenerator.kt +++ b/compiler/src/main/java/io/github/landerlyoung/jenny/NativeProxyGenerator.kt @@ -38,6 +38,7 @@ import gg.jte.resolve.DirectoryCodeResolver; import gg.jte.TemplateOutput; import gg.jte.output.StringOutput; import gg.jte.html.*; +import java.io.File /** * Author: landerlyoung@gmail.com @@ -45,13 +46,15 @@ import gg.jte.html.*; * Time: 00:30 * Life with Passion, Code with Creativity. */ -class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: NativeProxyConfig) : AbsCodeGenerator(env, clazz) { +class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: NativeProxyConfig) : + AbsCodeGenerator(env, clazz) { data class NativeProxyConfig( - val allMethods: Boolean, - val allFields: Boolean, - val namespace: String, - val onlyPublic: Boolean) { + val allMethods: Boolean, + val allFields: Boolean, + val namespace: String, + val onlyPublic: Boolean + ) { constructor(proxy: NativeProxy) : this(proxy.allMethods, proxy.allFields, proxy.namespace, false) } @@ -86,34 +89,35 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na private lateinit var templateEngine: TemplateEngine - public class JteData( - public val mCppClassName: String, - public val mSimpleClassName: String, - public val mNamespaceHelper: NamespaceHelper, - public val mSlashClassName: String, - public val mEnv: Environment, - public var param: String, - public var returnType: String, - public var methodPrologue: String, - public var isStatic : Boolean = false, - public var useJniHelper : Boolean = false, - public var clazz : TypeElement? = null, - public var method : MethodOverloadResolver.MethodRecord? = null, - public val mHelper: HandyHelper -) { - - } - private val jteData: JteData = JteData(cppClassName, mSimpleClassName, - mNamespaceHelper, - mSlashClassName, mEnv, - "", "", "", false, false, null, null, mHelper) + private val jteData = JteData( + className = cppClassName, + simpleClassName = mSimpleClassName, + namespaceHelper = mNamespaceHelper, + slashClassName = mSlashClassName, + environment = mEnv, + handyHelper = mHelper + ) + private var useTemplates = mEnv.configurations.useTemplates + init { mHeaderName = mNamespaceHelper.fileNamePrefix + "${cppClassName}.h" mSourceName = mNamespaceHelper.fileNamePrefix + "${cppClassName}.cpp" - if (mEnv.configurations.useTemplates) { - val codeResolver = DirectoryCodeResolver(Path.of(mEnv.configurations.templateDirectory)) - templateEngine = TemplateEngine.create(codeResolver!!, Path.of(mEnv.configurations.templateDirectory), ContentType.Plain, NativeProxyGenerator::class.java.classLoader) - templateEngine.precompileAll() + if (useTemplates) { + val path: String = mEnv.configurations.templateDirectory + ?: (System.getProperty("user.dir") + "/templates") + if (!File(path).exists()) { + error("Templates folder does not exist failed to generate using templates. Attempting without templates") + useTemplates = false + } else { + val codeResolver = DirectoryCodeResolver(Path.of(path)) + templateEngine = TemplateEngine.create( + codeResolver, + Path.of(path), + ContentType.Plain, + NativeProxyGenerator::class.java.classLoader + ) + templateEngine.precompileAll() + } } } @@ -141,49 +145,58 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na try { log("write native proxy file [$mHeaderName]") buildString { - if (mEnv.configurations.useTemplates) { + if (useTemplates) { val jteOutput = StringOutput() templateEngine.render("header_preamble.kte", jteData, jteOutput) append(jteOutput.toString()) } else { append(Constants.AUTO_GENERATE_NOTICE) - append(""" + append( + """ |#pragma once | |#include <jni.h> |#include <assert.h> - |""".trimMargin()) + |""".trimMargin() + ) if (mEnv.configurations.threadSafe) { - append(""" + append( + """ |#include <atomic> |#include <mutex> | - |""".trimMargin()) + |""".trimMargin() + ) } if (mEnv.configurations.useJniHelper) { - append(""" + append( + """ |#include "jnihelper.h" | - |""".trimMargin()) + |""".trimMargin() + ) } - append(""" + append( + """ |${mNamespaceHelper.beginNamespace()} |class $cppClassName { | |public: | static constexpr auto FULL_CLASS_NAME = "$mSlashClassName"; | - |""".trimMargin()) + |""".trimMargin() + ) } buildConstantsIdDeclare() - if (mEnv.configurations.useTemplates) { + if (useTemplates) { val jteOutput = StringOutput(); templateEngine.render("header_initfunctions.kte", jteData, jteOutput) append(jteOutput.toString()) } else { - append(""" + append( + """ | |public: | @@ -196,7 +209,8 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na | assert(initClazzSuccess); | } | - |""".trimMargin()) + |""".trimMargin() + ) } buildConstructorDefines(false) @@ -207,58 +221,13 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na generateForJniHelper() } - if (mEnv.configurations.useTemplates) { - val jteOutput = StringOutput(); - templateEngine.render("header_initvars.kte", jteData, jteOutput) - append(jteOutput.toString()) - } else { - append(""" - | - |private: - | struct ClassInitState { - | - """.trimMargin()) - - if (mEnv.configurations.threadSafe) { - append(""" - | // thread safe init - | std::atomic_bool sInited {}; - | std::mutex sInitLock {}; - |""".trimMargin()) - } else { - append(" bool sInited = false;\n") - } - append(""" - | - | jclass sClazz = nullptr; - | - """.trimMargin()) - } + headerInitPreDefinition() buildConstructorIdDeclare() buildMethodIdDeclare() buildFieldIdDeclare() - if (mEnv.configurations.useTemplates) { - val jteOutput = StringOutput(); - templateEngine.render("header_postamble.kte", jteData, jteOutput) - append(jteOutput.toString()) - } else { - append(""" - | }; // endof struct ClassInitState - | - | static inline ClassInitState& getClassInitState() { - | static ClassInitState classInitState; - | return classInitState; - | } - | - | - """.trimMargin()) - - append("};\n") - append(mNamespaceHelper.endNamespace()) - append("\n\n") - } + headerInitPostDefinition() if (mEnv.configurations.headerOnlyProxy) { append("\n\n") @@ -276,7 +245,8 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na } private fun StringBuilder.generateForJniHelper() { - append(""" + append( + """ | // ====== jni helper ====== |private: | ::jenny::LocalRef<jobject> _local; @@ -310,45 +280,111 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na | assertInited(::jenny::Env().get()); | } | - |""".trimMargin()) + |""".trimMargin() + ) buildConstructorDefines(true) buildMethodDefines(true) buildFieldDefines(true) } + private fun StringBuilder.headerInitPreDefinition() { + if (useTemplates) { + val jteOutput = StringOutput(); + templateEngine.render("header_initvars.kte", jteData, jteOutput) + append(jteOutput.toString()) + } else { + append( + """ + | + |private: + | struct ClassInitState { + | + """.trimMargin() + ) + + if (mEnv.configurations.threadSafe) { + append( + """ + | // thread safe init + | std::atomic_bool sInited {}; + | std::mutex sInitLock {}; + |""".trimMargin() + ) + } else { + append(" bool sInited = false;\n") + } + append( + """ + | + | jclass sClazz = nullptr; + | + """.trimMargin() + ) + } + } + + private fun StringBuilder.headerInitPostDefinition() { + if (useTemplates) { + val jteOutput = StringOutput(); + templateEngine.render("header_postamble.kte", jteData, jteOutput) + append(jteOutput.toString()) + } else { + append( + """ + | }; // endof struct ClassInitState + | + | static inline ClassInitState& getClassInitState() { + | static ClassInitState classInitState; + | return classInitState; + | } + | + | + """.trimMargin() + ) + + append("};\n") + append(mNamespaceHelper.endNamespace()) + append("\n\n") + } + } + private fun generateSource() { mEnv.createOutputFile(Constants.JENNY_GEN_DIR_PROXY, mSourceName) - .use { out -> - try { - log("write native proxy file [$mSourceName]") - buildString { - generateSourceContent(false) - }.let { content -> - out.write(content.toByteArray(Charsets.UTF_8)) - } - } catch (e: IOException) { - warn("generate header file $mHeaderName failed!") + .use { out -> + try { + log("write native proxy file [$mSourceName]") + buildString { + generateSourceContent(false) + }.let { content -> + out.write(content.toByteArray(Charsets.UTF_8)) } + } catch (e: IOException) { + warn("generate header file $mHeaderName failed!") } + } } private fun StringBuilder.generateSourceContent(headerOnly: Boolean) { if (!headerOnly) { append(Constants.AUTO_GENERATE_NOTICE) - append(""" + append( + """ |#include "$mHeaderName" | - |""".trimMargin()) + |""".trimMargin() + ) } if (!mEnv.configurations.errorLoggerFunction.isNullOrBlank()) { - append(""" + append( + """ | |// external logger function passed by ${Configurations.ERROR_LOGGER_FUNCTION} |void ${mEnv.configurations.errorLoggerFunction}(JNIEnv* env, const char* error); | - |""".trimMargin()) + |""".trimMargin() + ) } append(mNamespaceHelper.beginNamespace()) @@ -368,29 +404,63 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na append('\n') } + data class MethodIdDeclaration( + val helper: HandyHelper, + val listOfMethods: List<MethodOverloadResolver.MethodRecord> + ) + private fun StringBuilder.buildConstructorIdDeclare() { - mConstructors.forEach { r -> - append(" jmethodID ${mHelper.getConstructorName(r.index)} = nullptr;\n") + if (useTemplates) { + val stringOutput = StringOutput() + val constructors = MethodIdDeclaration(mHelper, mConstructors) + templateEngine.render("constructors_ids_declarations.kte", constructors, stringOutput) + append(stringOutput.toString()) + } else { + mConstructors.forEach { r -> + append(" jmethodID ${mHelper.getConstructorName(r.index)} = nullptr;\n") + } + append('\n') } - append('\n') } private fun StringBuilder.buildMethodIdDeclare() { - mMethods.forEach { r -> - append(" jmethodID ${getMethodName(r.method, r.index)} = nullptr;\n") + if (useTemplates) { + val stringOutput = StringOutput() + val methods = MethodIdDeclaration(mHelper, mMethods) + templateEngine.render("methods_ids_declarations.kte", methods, stringOutput) + append(stringOutput.toString()) + } else { + mMethods.forEach { r -> + append(" jmethodID ${mHelper.getMethodName(r.method, r.index)} = nullptr;\n") + } + append('\n') } - append('\n') } + data class FieldIdDeclaration( + val helper: HandyHelper, + val listOfFields: List<VariableElement> + ) + private fun StringBuilder.buildFieldIdDeclare() { - mFields.forEachIndexed { index, field -> - if (field.constantValue != null) { - warn("you are trying to add getter/setter to a compile-time constant " - + mClassName + "." + field.simpleName.toString()) + if (useTemplates) { + val stringOutput = StringOutput() + val fields = FieldIdDeclaration(mHelper, mFields) + templateEngine.render("fields_ids_declarations.kte", fields, stringOutput) + append(stringOutput.toString()) + } else { + mFields.forEachIndexed { index, field -> + if (field.constantValue != null) { + warn( + "you are trying to add getter/setter to a compile-time constant " + + mClassName + "." + field.simpleName.toString() + ) + } + append(" jfieldID ${mHelper.getFieldName(field, index)} = nullptr;\n") } - append(" jfieldID ${getFieldName(field, index)} = nullptr;\n") + append('\n') } - append('\n') + } private fun StringBuilder.buildConstructorDefines(useJniHelper: Boolean) { @@ -398,24 +468,35 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na val param = makeParam(true, useJniHelper, getJniMethodParam(r.method, useJniHelper)) val returnType = if (useJniHelper) cppClassName else "jobject" - if (mEnv.configurations.useTemplates) { - val jteOutput = StringOutput() - jteData.useJniHelper = useJniHelper - jteData.clazz = mClazz - jteData.method = r - jteData.returnType = returnType - jteData.methodPrologue = methodPrologue(true, useJniHelper) - templateEngine.render("constructor_definition.kte", jteData, jteOutput) - append(jteOutput.toString()) + if (useTemplates) { + val jteOutput = StringOutput() + jteData.param = param + jteData.useJniHelper = useJniHelper + jteData.clazz = mClazz + jteData.method = r + jteData.returnType = returnType + jteData.methodPrologue = methodPrologue(true, useJniHelper) + templateEngine.render("constructor_definition.kte", jteData, jteOutput) + append(jteOutput.toString()) } else { - append(""" - | // construct: ${mHelper.getModifiers(r.method)} ${mSimpleClassName}(${mHelper.getJavaMethodParam(r.method)}) + append( + """ + | // construct: ${mHelper.getModifiers(r.method)} ${mSimpleClassName}(${ + mHelper.getJavaMethodParam( + r.method + ) + }) | static $returnType newInstance${r.resolvedPostFix}(${param}) { | ${methodPrologue(true, useJniHelper)} - | return env->NewObject(${mHelper.getClassState(mHelper.getClazz())}, ${mHelper.getClassState(mHelper.getConstructorName(r.index))}${mHelper.getJniMethodParamVal(mClazz, r.method, useJniHelper)}); + | return env->NewObject(${mHelper.getClassState(mHelper.getClazz())}, ${ + mHelper.getClassState( + mHelper.getConstructorName(r.index) + ) + }${mHelper.getJniMethodParamVal(mClazz, r.method, useJniHelper)}); | } | - |""".trimMargin()) + |""".trimMargin() + ) } } @@ -437,11 +518,17 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na append(" // for jni helper\n") } - append(""" - | // method: ${mHelper.getModifiers(m)} ${m.returnType} ${m.simpleName}(${mHelper.getJavaMethodParam(m)}) + append( + """ + | // method: ${mHelper.getModifiers(m)} ${m.returnType} ${m.simpleName}(${ + mHelper.getJavaMethodParam( + m + ) + }) | ${staticMod}${functionReturnType} ${m.simpleName}${r.resolvedPostFix}(${jniParam}) ${constMod}{ | ${methodPrologue(isStatic, useJniHelper)} - |""".trimMargin()) + |""".trimMargin() + ) if (m.returnType.kind !== TypeKind.VOID) { append(" return ") @@ -459,7 +546,11 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na val static = if (isStatic) "Static" else "" val classOrObj = if (isStatic) mHelper.getClassState(mHelper.getClazz()) else "thiz" - append("env->Call${static}${getTypeForJniCall(m.returnType)}Method(${classOrObj}, ${mHelper.getClassState(getMethodName(m, r.index))}${mHelper.getJniMethodParamVal(mClazz, m, useJniHelper)})") + append( + "env->Call${static}${getTypeForJniCall(m.returnType)}Method(${classOrObj}, ${ + mHelper.getClassState(mHelper.getMethodName(m, r.index)) + }${mHelper.getJniMethodParamVal(mClazz, m, useJniHelper)})" + ) if (returnTypeNeedCast(jniReturnType)) { append(")") } @@ -478,7 +569,7 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na val isStatic = f.modifiers.contains(Modifier.STATIC) val camelCaseName = f.simpleName.toString().capitalize(Locale.ROOT) val getterSetters = hasGetterSetter(f) - val fieldId = getFieldName(f, index) + val fieldId = mHelper.getFieldName(f, index) val typeForJniCall = getTypeForJniCall(f.asType()) @@ -498,11 +589,13 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na val jniReturnType = mHelper.toJNIType(f.asType()) val functionReturnType = f.asType().toJniTypeForReturn(useJniHelper) val param = makeParam(isStatic, useJniHelper, "") - append(""" + append( + """ | $comment | ${staticMod}$functionReturnType get${camelCaseName}(${param}) ${constMod}{ | ${methodPrologue(isStatic, useJniHelper)} - | return """.trimMargin()) + | return """.trimMargin() + ) if (useJniHelper && mHelper.needWrapLocalRef(f.asType())) { append(functionReturnType).append("(") @@ -512,7 +605,13 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na append("reinterpret_cast<${jniReturnType}>(") } - append("${jniEnv}->Get${static}${typeForJniCall}Field(${classOrObj}, ${mHelper.getClassState(fieldId)})") + append( + "${jniEnv}->Get${static}${typeForJniCall}Field(${classOrObj}, ${ + mHelper.getClassState( + fieldId + ) + })" + ) if (returnTypeNeedCast(jniReturnType)) { append(")") @@ -520,68 +619,94 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na if (useJniHelper && mHelper.needWrapLocalRef(f.asType())) { append(")") } - append("""; + append( + """; | | } | - |""".trimMargin()) + |""".trimMargin() + ) } // setter if (getterSetters.contains(GetterSetter.SETTER)) { - val param = makeParam(isStatic, useJniHelper, "${f.asType().toJniTypeForParam(useJniHelper)} ${f.simpleName}") - val passedParam = if (useJniHelper && mHelper.needWrapLocalRef(f.asType())) "${f.simpleName}.get()" else f.simpleName - append(""" + val param = makeParam( + isStatic, + useJniHelper, + "${f.asType().toJniTypeForParam(useJniHelper)} ${f.simpleName}" + ) + val passedParam = + if (useJniHelper && mHelper.needWrapLocalRef(f.asType())) "${f.simpleName}.get()" else f.simpleName + append( + """ | $comment | ${staticMod}void set${camelCaseName}(${param}) ${constMod}{ | ${methodPrologue(isStatic, useJniHelper)} - | ${jniEnv}->Set${static}${typeForJniCall}Field(${classOrObj}, ${mHelper.getClassState(fieldId)}, ${passedParam}); + | ${jniEnv}->Set${static}${typeForJniCall}Field(${classOrObj}, ${ + mHelper.getClassState( + fieldId + ) + }, ${passedParam}); | } | - |""".trimMargin()) + |""".trimMargin() + ) } append('\n') } } private fun StringBuilder.buildNativeInitClass(headerOnly: Boolean) { - val prefix = if(headerOnly) "/*static*/ inline" else "/*static*/" - append(""" + val prefix = if (headerOnly) "/*static*/ inline" else "/*static*/" + append( + """ |${prefix} bool $cppClassName::initClazz(JNIEnv* env) { |#define JENNY_CHECK_NULL(val) \ | do { \ | if ((val) == nullptr) { \ - |""".trimMargin()) + |""".trimMargin() + ) if (!mEnv.configurations.errorLoggerFunction.isNullOrBlank()) { - append(""" + append( + """ | ${mEnv.configurations.errorLoggerFunction}(env, "can't init ${cppClassName}::" #val); \ - |""".trimMargin()) + |""".trimMargin() + ) } else { - append(""" + append( + """ | env->ExceptionDescribe(); \ - |""".trimMargin()) + |""".trimMargin() + ) } - append(""" + append( + """ | return false; \ | } \ | } while(false) | - |""".trimMargin()) + |""".trimMargin() + ) - append(""" - | auto& state = mHelper.getClassInitState(); - |""".trimMargin()) + append( + """ + | auto& state = getClassInitState(); + |""".trimMargin() + ) if (mEnv.configurations.threadSafe) { - append(""" + append( + """ | if (!state.sInited) { | std::lock_guard<std::mutex> lg(state.sInitLock); - |""".trimMargin()) + |""".trimMargin() + ) } - append(""" + append( + """ | if (!state.sInited) { | auto clazz = env->FindClass(FULL_CLASS_NAME); | JENNY_CHECK_NULL(clazz); @@ -589,35 +714,41 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na | env->DeleteLocalRef(clazz); | JENNY_CHECK_NULL(state.sClazz); | - |""".trimMargin()) + |""".trimMargin() + ) buildConstructorIdInit() buildMethodIdInit() buildFieldIdInit() - append(""" + append( + """ | state.sInited = true; | } - |""".trimMargin()) + |""".trimMargin() + ) if (mEnv.configurations.threadSafe) { append(" }\n") } - append(""" + append( + """ |#undef JENNY_CHECK_NULL | return true; |} | - |""".trimMargin()) + |""".trimMargin() + ) val lockGuard = if (mEnv.configurations.threadSafe) { "std::lock_guard<std::mutex> lg(state.sInitLock);" } else { "" } - append(""" + append( + """ |${prefix} void $cppClassName::releaseClazz(JNIEnv* env) { - | auto& state = mHelper.getClassInitState(); + | auto& state = getClassInitState(); | if (state.sInited) { | $lockGuard | if (state.sInited) { @@ -628,7 +759,8 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na | } |} | - |""".trimMargin()) + |""".trimMargin() + ) } private fun StringBuilder.buildConstructorIdInit() { @@ -637,11 +769,13 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na val name = "state.${mHelper.getConstructorName(r.index)}" val signature = mHelper.getBinaryMethodSignature(c) - append(""" + append( + """ | $name = env->GetMethodID(state.sClazz, "<init>", "$signature"); | JENNY_CHECK_NULL(${name}); | - |""".trimMargin()) + |""".trimMargin() + ) } append('\n') } @@ -649,73 +783,77 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na private fun StringBuilder.buildMethodIdInit() { mMethods.forEach { r -> val m = r.method - val name = "state.${getMethodName(m, r.index)}" + val name = "state.${mHelper.getMethodName(m, r.index)}" val static = if (m.modifiers.contains(Modifier.STATIC)) "Static" else "" val methodName = m.simpleName val signature = mHelper.getBinaryMethodSignature(m) - append(""" + append( + """ | $name = env->Get${static}MethodID(state.sClazz, "$methodName", "$signature"); | JENNY_CHECK_NULL(${name}); | - |""".trimMargin()) + |""".trimMargin() + ) } append('\n') } private fun StringBuilder.buildFieldIdInit() { mFields.forEachIndexed { index, f -> - val name = "state.${getFieldName(f, index)}" + val name = "state.${mHelper.getFieldName(f, index)}" val static = if (f.modifiers.contains(Modifier.STATIC)) "Static" else "" val fieldName = f.simpleName val signature = mHelper.getBinaryTypeSignature(f.asType()) - append(""" + append( + """ | $name = env->Get${static}FieldID(state.sClazz, "$fieldName", "$signature"); | JENNY_CHECK_NULL(${name}); | - |""".trimMargin()) + |""".trimMargin() + ) } append('\n') } private fun makeParam(vararg params: String): String = - params.filter { it.isNotEmpty() }.joinToString(", ") + params.filter { it.isNotEmpty() }.joinToString(", ") private fun makeParam(isStatic: Boolean, useJniHelper: Boolean, jniParam: String): String = - if (mEnv.configurations.useTemplates) { - val jteOutput = StringOutput() - jteData.param = jniParam - jteData.isStatic = isStatic - jteData.useJniHelper = useJniHelper - templateEngine.render("param.kte", jteData, jteOutput) - jteOutput.toString().trim() - } else if (!useJniHelper) { - if (isStatic) { - makeParam("JNIEnv* env", jniParam) - } else { - makeParam("JNIEnv* env", "jobject thiz", jniParam) - } + if (useTemplates) { + val jteOutput = StringOutput() + jteData.param = jniParam + jteData.isStatic = isStatic + jteData.useJniHelper = useJniHelper + templateEngine.render("param.kte", jteData, jteOutput) + jteOutput.toString().trim() + } else if (!useJniHelper) { + if (isStatic) { + makeParam("JNIEnv* env", jniParam) } else { - jniParam + makeParam("JNIEnv* env", "jobject thiz", jniParam) } + } else { + jniParam + } private fun methodPrologue(isStatic: Boolean, useJniHelper: Boolean): String = - if (mEnv.configurations.useTemplates) { - val jteOutput = StringOutput() - jteData.isStatic = isStatic - jteData.useJniHelper = useJniHelper - templateEngine.render("method_prologue.kte", jteData, jteOutput) - jteOutput.toString().trim() - } else if (useJniHelper) { - if (isStatic) { - "::jenny::Env env; assertInited(env.get());" - } else { - "::jenny::Env env; ::jenny::LocalRef<jobject> jennyLocalRef = getThis(false); jobject thiz = jennyLocalRef.get();" - } + if (useTemplates) { + val jteOutput = StringOutput() + jteData.isStatic = isStatic + jteData.useJniHelper = useJniHelper + templateEngine.render("method_prologue.kte", jteData, jteOutput) + jteOutput.toString().trim() + } else if (useJniHelper) { + if (isStatic) { + "::jenny::Env env; assertInited(env.get());" } else { - "assertInited(env);" + "::jenny::Env env; ::jenny::LocalRef<jobject> jennyLocalRef = getThis(false); jobject thiz = jennyLocalRef.get();" } + } else { + "assertInited(env);" + } private fun shouldGenerateMethod(m: ExecutableElement): Boolean { val annotation = m.getAnnotation(NativeMethodProxy::class.java) @@ -779,64 +917,58 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na "jshortArray", "jintArray", "jlongArray", "jfloatArray", "jdoubleArray", "jthrowable", "jweak" -> true + else -> // primitive type or jobject or void false } } - private fun getMethodName(e: ExecutableElement, index: Int): String { - return "sMethod_" + e.simpleName + "_" + index - } - - private fun getFieldName(e: Element, index: Int): String { - return "sField_" + e.simpleName + "_" + index - } - private fun findConstructors() { mClazz.enclosedElements - .asSequence() - .filter { it.kind == ElementKind.CONSTRUCTOR } - .map { it as ExecutableElement } - .filter { visibilityMatched(it) && shouldGenerateMethod(it) } - .toList() - .let { - MethodOverloadResolver(mHelper, this::getJniMethodParamTypes).resolve(it) - .let { mConstructors.addAll(it) } - } + .asSequence() + .filter { it.kind == ElementKind.CONSTRUCTOR } + .map { it as ExecutableElement } + .filter { visibilityMatched(it) && shouldGenerateMethod(it) } + .toList() + .let { + MethodOverloadResolver(mHelper, this::getJniMethodParamTypes).resolve(it) + .let { mConstructors.addAll(it) } + } } private fun findMethods() { mClazz.enclosedElements - .asSequence() - .filter { it.kind == ElementKind.METHOD } - .map { it as ExecutableElement } - .filter { visibilityMatched(it) && shouldGenerateMethod(it) } - .groupBy { it.simpleName.toString() } - .forEach { (simpleName, methodList) -> - mMethodSimpleName.add(simpleName) - MethodOverloadResolver(mHelper, this::getJniMethodParamTypes).resolve(methodList).let { + .asSequence() + .filter { it.kind == ElementKind.METHOD } + .map { it as ExecutableElement } + .filter { visibilityMatched(it) && shouldGenerateMethod(it) } + .groupBy { it.simpleName.toString() } + .forEach { (simpleName, methodList) -> + mMethodSimpleName.add(simpleName) + MethodOverloadResolver(mHelper, this::getJniMethodParamTypes).resolve(methodList) + .let { mMethods.addAll(it) } - } + } } private fun findConstants() { mClazz.enclosedElements - .asSequence() - .filter { - it.kind.isField && visibilityMatched(it) - && it.modifiers.containsAll(listOf(Modifier.STATIC, Modifier.FINAL)) - && (it as VariableElement).constantValue != null - } - .forEach { mConstants.add(it as VariableElement) } + .asSequence() + .filter { + it.kind.isField && visibilityMatched(it) + && it.modifiers.containsAll(listOf(Modifier.STATIC, Modifier.FINAL)) + && (it as VariableElement).constantValue != null + } + .forEach { mConstants.add(it as VariableElement) } } private fun findFields() { mClazz.enclosedElements - .asSequence() - .filter { it.kind.isField && shouldGenerateField(it) && visibilityMatched(it) } - .forEach { mFields.add(it as VariableElement) } + .asSequence() + .filter { it.kind.isField && shouldGenerateField(it) && visibilityMatched(it) } + .forEach { mFields.add(it as VariableElement) } } private fun visibilityMatched(element: Element): Boolean { @@ -885,15 +1017,15 @@ class NativeProxyGenerator(env: Environment, clazz: TypeElement, nativeProxy: Na val enclosingElement = mClazz.enclosingElement // nested class has an this$0 in its constructor append(enclosingElement.asType().toJniTypeForParam(useJniHelper)) - .append(" ") - .append("enclosingClass") + .append(" ") + .append("enclosingClass") needComma = true } m.parameters.forEach { p -> if (needComma) append(", ") append(p.asType().toJniTypeForParam(useJniHelper)) - .append(" ") - .append(p.simpleName) + .append(" ") + .append(p.simpleName) needComma = true } } diff --git a/sample-android/src/main/cpp/CMakeLists.txt b/sample-android/src/main/cpp/CMakeLists.txt index 2706cbd..bdcaa33 100644 --- a/sample-android/src/main/cpp/CMakeLists.txt +++ b/sample-android/src/main/cpp/CMakeLists.txt @@ -1,14 +1,19 @@ -cmake_minimum_required(VERSION 3.4.1) - -include_directories(gen) - -file(GLOB SRC - ./*.cpp - ./*.h - ) - -add_library(hello-jenny SHARED - ${SRC} - ) - -target_link_libraries(hello-jenny log)
\ No newline at end of file +#cmake_minimum_required(VERSION 3.4.1) +# +#project(HelloJenny VERSION 1.0 LANGUAGES CXX) +#set(CMAKE_CXX_STANDARD 11) +#set(CMAKE_CXX_STANDARD_REQUIRED ON) +# +#file(GLOB_RECURSE SRC_CPP +# ${CMAKE_SOURCE_DIR}/gen/jenny/glue/cpp/*.cpp +# ${CMAKE_SOURCE_DIR}/gen/jenny/proxy/*.cpp +# ${CMAKE_SOURCE_DIR}/*.cpp +#) +#file(GLOB_RECURSE SRC_H +# ${CMAKE_SOURCE_DIR}/gen/jenny/glue/header/*.h +# ${CMAKE_SOURCE_DIR}/gen/jenny/proxy/*.h +#) +#set(SRC ${SRC_CPP} ${SRC_H}) +#add_library(hello-jenny SHARED ${SRC}) +#target_include_directories(hello-jenny PRIVATE ${CMAKE_SOURCE_DIR}/gen/jenny) +#target_link_libraries(hello-jenny PRIVATE log)
\ No newline at end of file diff --git a/sample-android/src/main/cpp/jni_onload.cpp b/sample-android/src/main/cpp/jni_onload.cpp index 15b2b61..60557af 100644 --- a/sample-android/src/main/cpp/jni_onload.cpp +++ b/sample-android/src/main/cpp/jni_onload.cpp @@ -13,16 +13,19 @@ #include "ComputeIntensiveClass.h" #include "NestedNativeClass.h" #include "NativeDrawable.h" -#include "gen/GenericProxy.h" -#include "gen/jnihelper.h" -#include "gen/jenny_fusion_proxies.h" - -#include "gen/java_okhttp_BuilderProxy.h" -#include "gen/java_okhttp_OkHttpClientProxy.h" -#include "gen/java_okhttp_RequestProxy.h" -#include "gen/java_okhttp_CallProxy.h" -#include "gen/java_okhttp_ResponseProxy.h" -#include "gen/java_okhttp_ResponseBodyProxy.h" +#include "proxy/GenericProxy.h" +#include "proxy/jnihelper.h" +#include "proxy/jenny_fusion_proxies.h" + +#include "proxy/java_okhttp_BuilderProxy.h" +#include "proxy/java_okhttp_OkHttpClientProxy.h" +#include "proxy/java_okhttp_RequestProxy.h" +#include "proxy/java_okhttp_CallProxy.h" +#include "proxy/java_okhttp_ResponseProxy.h" +#include "proxy/java_okhttp_ResponseBodyProxy.h" +#include "glue/header/NativeDrawable.h" +#include "glue/header/ComputeIntensiveClass.h" + JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) { JNIEnv* env; diff --git a/sample-android/templates/constructor_definition.kte b/sample-android/templates/constructor_definition.kte index fedd89d..91361f2 100644 --- a/sample-android/templates/constructor_definition.kte +++ b/sample-android/templates/constructor_definition.kte @@ -1,12 +1,12 @@ -@import io.github.landerlyoung.jenny.NativeProxyGenerator.JteData +@import io.github.landerlyoung.jenny.JteData @import io.github.landerlyoung.jenny.Constants @import io.github.landerlyoung.jenny.HandyHelper @import io.github.landerlyoung.jenny.MethodOverloadResolver.MethodRecord @param jteData: JteData - // construct: ${jteData.mHelper.getModifiers(jteData.method!!.method)} ${jteData.mSimpleClassName}(${jteData.mHelper.getJavaMethodParam(jteData.method!!.method)}) + // construct: ${jteData.handyHelper.getModifiers(jteData.method!!.method)} ${jteData.simpleClassName}(${jteData.handyHelper.getJavaMethodParam(jteData.method!!.method)}) static ${jteData.returnType} newInstance${jteData.method!!.resolvedPostFix}(${jteData.param}) { ${jteData.methodPrologue} - return env->NewObject(${jteData.mHelper.getClassState(jteData.mHelper.getClazz())}, ${jteData.mHelper.getClassState(jteData.mHelper.getConstructorName(jteData.method!!.index))}${jteData.mHelper.getJniMethodParamVal(jteData.clazz!!, jteData.method!!.method, jteData.useJniHelper)}); + return env->NewObject(${jteData.handyHelper.getClassState(jteData.handyHelper.getClazz())}, ${jteData.handyHelper.getClassState(jteData.handyHelper.getConstructorName(jteData.method!!.index))}${jteData.handyHelper.getJniMethodParamVal(jteData.clazz!!, jteData.method!!.method, jteData.useJniHelper)}); } diff --git a/sample-android/templates/constructors_ids_declarations.kte b/sample-android/templates/constructors_ids_declarations.kte new file mode 100644 index 0000000..acd0a7d --- /dev/null +++ b/sample-android/templates/constructors_ids_declarations.kte @@ -0,0 +1,9 @@ +@import io.github.landerlyoung.jenny.NativeProxyGenerator.MethodIdDeclaration +@import io.github.landerlyoung.jenny.HandyHelper +@import io.github.landerlyoung.jenny.MethodOverloadResolver.MethodRecord + +@param methodIdDeclaration:MethodIdDeclaration + +@for(method:MethodRecord in methodIdDeclaration.listOfMethods) + jmethodID ${methodIdDeclaration.helper.getConstructorName(method.index)} = nullptr; +@endfor
\ No newline at end of file diff --git a/sample-android/templates/fields_ids_declarations.kte b/sample-android/templates/fields_ids_declarations.kte new file mode 100644 index 0000000..5e1679b --- /dev/null +++ b/sample-android/templates/fields_ids_declarations.kte @@ -0,0 +1,9 @@ +@import io.github.landerlyoung.jenny.NativeProxyGenerator.FieldIdDeclaration +@import io.github.landerlyoung.jenny.HandyHelper +@import javax.lang.model.element.VariableElement + +@param fieldIdDeclaration:FieldIdDeclaration + +@for((index, fieldElement) in fieldIdDeclaration.listOfFields.withIndex()) + jfieldID ${fieldIdDeclaration.helper.getFieldName(fieldElement, index)} = nullptr; +@endfor
\ No newline at end of file diff --git a/sample-android/templates/header_initfunctions.kte b/sample-android/templates/header_initfunctions.kte index cad0890..4949f36 100644 --- a/sample-android/templates/header_initfunctions.kte +++ b/sample-android/templates/header_initfunctions.kte @@ -1,4 +1,4 @@ -@import io.github.landerlyoung.jenny.NativeProxyGenerator.JteData +@import io.github.landerlyoung.jenny.JteData @import io.github.landerlyoung.jenny.Constants @param jteData: JteData diff --git a/sample-android/templates/header_initvars.kte b/sample-android/templates/header_initvars.kte index fd93466..b59357d 100644 --- a/sample-android/templates/header_initvars.kte +++ b/sample-android/templates/header_initvars.kte @@ -1,4 +1,4 @@ -@import io.github.landerlyoung.jenny.NativeProxyGenerator.JteData +@import io.github.landerlyoung.jenny.JteData @import io.github.landerlyoung.jenny.Constants @param jteData: JteData @@ -6,7 +6,7 @@ private: struct ClassInitState { -@if (jteData.mEnv.configurations.threadSafe) +@if (jteData.environment.configurations.threadSafe) // thread safe init std::atomic_bool sInited {}; std::mutex sInitLock {}; diff --git a/sample-android/templates/header_postamble.kte b/sample-android/templates/header_postamble.kte index cde05c9..fc6b0e0 100644 --- a/sample-android/templates/header_postamble.kte +++ b/sample-android/templates/header_postamble.kte @@ -1,4 +1,4 @@ -@import io.github.landerlyoung.jenny.NativeProxyGenerator.JteData +@import io.github.landerlyoung.jenny.JteData @import io.github.landerlyoung.jenny.Constants @param jteData: JteData @@ -11,5 +11,5 @@ return classInitState; } }; -${jteData.mNamespaceHelper.endNamespace()} +${jteData.namespaceHelper.endNamespace()} diff --git a/sample-android/templates/header_preamble.kte b/sample-android/templates/header_preamble.kte index 4b076a9..6d4a9c2 100644 --- a/sample-android/templates/header_preamble.kte +++ b/sample-android/templates/header_preamble.kte @@ -1,4 +1,4 @@ -@import io.github.landerlyoung.jenny.NativeProxyGenerator.JteData +@import io.github.landerlyoung.jenny.JteData @import io.github.landerlyoung.jenny.Constants @param jteData: JteData @@ -9,19 +9,19 @@ ${Constants.AUTO_GENERATE_NOTICE} #include <jni.h> #include <assert.h> -@if (jteData.mEnv.configurations.threadSafe) +@if (jteData.environment.configurations.threadSafe) #include <atomic> #include <mutex> @endif -@if (jteData.mEnv.configurations.useJniHelper) +@if (jteData.environment.configurations.useJniHelper) #include "jnihelper.h" @endif -${jteData.mNamespaceHelper.beginNamespace()} -class ${jteData.mCppClassName} { +${jteData.namespaceHelper.beginNamespace()} +class ${jteData.className} { public: - static constexpr auto FULL_CLASS_NAME = "${jteData.mSlashClassName}"; + static constexpr auto FULL_CLASS_NAME = "${jteData.slashClassName}"; diff --git a/sample-android/templates/method_prologue.kte b/sample-android/templates/method_prologue.kte index 82d0bd0..8e28bf8 100644 --- a/sample-android/templates/method_prologue.kte +++ b/sample-android/templates/method_prologue.kte @@ -1,4 +1,4 @@ -@import io.github.landerlyoung.jenny.NativeProxyGenerator.JteData +@import io.github.landerlyoung.jenny.JteData @import io.github.landerlyoung.jenny.Constants @import io.github.landerlyoung.jenny.HandyHelper @import io.github.landerlyoung.jenny.MethodOverloadResolver.MethodRecord diff --git a/sample-android/templates/methods_ids_declarations.kte b/sample-android/templates/methods_ids_declarations.kte new file mode 100644 index 0000000..16afca0 --- /dev/null +++ b/sample-android/templates/methods_ids_declarations.kte @@ -0,0 +1,9 @@ +@import io.github.landerlyoung.jenny.NativeProxyGenerator.MethodIdDeclaration +@import io.github.landerlyoung.jenny.HandyHelper +@import io.github.landerlyoung.jenny.MethodOverloadResolver.MethodRecord + +@param methodIdDeclaration:MethodIdDeclaration + +@for(method:MethodRecord in methodIdDeclaration.listOfMethods) + jmethodID ${methodIdDeclaration.helper.getMethodName(method.method , method.index)} = nullptr; +@endfor
\ No newline at end of file diff --git a/sample-android/templates/param.kte b/sample-android/templates/param.kte index f72aeb1..e788593 100644 --- a/sample-android/templates/param.kte +++ b/sample-android/templates/param.kte @@ -1,4 +1,4 @@ -@import io.github.landerlyoung.jenny.NativeProxyGenerator.JteData +@import io.github.landerlyoung.jenny.JteData @import io.github.landerlyoung.jenny.Constants @param jteData: JteData diff --git a/templates/constructor_definition.kte b/templates/constructor_definition.kte new file mode 100644 index 0000000..32ba70d --- /dev/null +++ b/templates/constructor_definition.kte @@ -0,0 +1,12 @@ +@import io.github.landerlyoung.jenny.JteData +@import io.github.landerlyoung.jenny.Constants +@import io.github.landerlyoung.jenny.HandyHelper +@import io.github.landerlyoung.jenny.MethodOverloadResolver.MethodRecord + +@param jteData: JteData + + // construct: ${jteData.mHelper.getModifiers(jteData.method!!.method)} ${jteData.mSimpleClassName}(${jteData.mHelper.getJavaMethodParam(jteData.method!!.method)}) + static ${jteData.returnType} newInstance${jteData.method!!.resolvedPostFix}(${jteData.param}) { + ${jteData.methodPrologue} + return env->NewObject(${jteData.mHelper.getClassState(jteData.mHelper.getClazz())}, ${jteData.mHelper.getClassState(jteData.mHelper.getConstructorName(jteData.method!!.index))}${jteData.mHelper.getJniMethodParamVal(jteData.clazz!!, jteData.method!!.method, jteData.useJniHelper)}); + } diff --git a/templates/header_initfunctions.kte b/templates/header_initfunctions.kte new file mode 100644 index 0000000..4949f36 --- /dev/null +++ b/templates/header_initfunctions.kte @@ -0,0 +1,15 @@ +@import io.github.landerlyoung.jenny.JteData +@import io.github.landerlyoung.jenny.Constants + +@param jteData: JteData + +public: + + static bool initClazz(JNIEnv* env); + + static void releaseClazz(JNIEnv* env); + + static void assertInited(JNIEnv* env) { + auto initClazzSuccess = initClazz(env); + assert(initClazzSuccess); + } diff --git a/templates/header_initvars.kte b/templates/header_initvars.kte new file mode 100644 index 0000000..fe6769c --- /dev/null +++ b/templates/header_initvars.kte @@ -0,0 +1,16 @@ +@import io.github.landerlyoung.jenny.JteData +@import io.github.landerlyoung.jenny.Constants + +@param jteData: JteData + +private: + struct ClassInitState { + +@if (jteData.mEnv.configurations.threadSafe) + // thread safe init + std::atomic_bool sInited {}; + std::mutex sInitLock {}; +@else + bool sInited = false;\n") +@endif + jclass sClazz = nullptr; diff --git a/templates/header_postamble.kte b/templates/header_postamble.kte new file mode 100644 index 0000000..d3c5480 --- /dev/null +++ b/templates/header_postamble.kte @@ -0,0 +1,15 @@ +@import io.github.landerlyoung.jenny.JteData +@import io.github.landerlyoung.jenny.Constants + +@param jteData: JteData + + + }; // endof struct ClassInitState + + static inline ClassInitState& getClassInitState() { + static ClassInitState classInitState; + return classInitState; + } +}; +${jteData.mNamespaceHelper.endNamespace()} + diff --git a/templates/header_preamble.kte b/templates/header_preamble.kte new file mode 100644 index 0000000..c731c3b --- /dev/null +++ b/templates/header_preamble.kte @@ -0,0 +1,27 @@ +@import io.github.landerlyoung.jenny.JteData +@import io.github.landerlyoung.jenny.Constants + +@param jteData: JteData + +${Constants.AUTO_GENERATE_NOTICE} +#pragma once + +#include <jni.h> +#include <assert.h> + +@if (jteData.mEnv.configurations.threadSafe) +#include <atomic> +#include <mutex> +@endif + +@if (jteData.mEnv.configurations.useJniHelper) +#include "jnihelper.h" +@endif + +${jteData.mNamespaceHelper.beginNamespace()} +class ${jteData.mCppClassName} { + +public: + static constexpr auto FULL_CLASS_NAME = "${jteData.mSlashClassName}"; + + diff --git a/templates/method_prologue.kte b/templates/method_prologue.kte new file mode 100644 index 0000000..8e28bf8 --- /dev/null +++ b/templates/method_prologue.kte @@ -0,0 +1,16 @@ +@import io.github.landerlyoung.jenny.JteData +@import io.github.landerlyoung.jenny.Constants +@import io.github.landerlyoung.jenny.HandyHelper +@import io.github.landerlyoung.jenny.MethodOverloadResolver.MethodRecord + +@param jteData: JteData + +@if (jteData.useJniHelper) + @if (jteData.isStatic) +::jenny::Env env; assertInited(env.get()); + @else +::jenny::Env env; ::jenny::LocalRef<jobject> jennyLocalRef = getThis(false); jobject thiz = jennyLocalRef.get(); + @endif +@else +assertInited(env); +@endif
\ No newline at end of file diff --git a/templates/param.kte b/templates/param.kte new file mode 100644 index 0000000..e788593 --- /dev/null +++ b/templates/param.kte @@ -0,0 +1,22 @@ +@import io.github.landerlyoung.jenny.JteData +@import io.github.landerlyoung.jenny.Constants + +@param jteData: JteData + +@if (!jteData.useJniHelper) + @if (jteData.isStatic) + @if (jteData.param != "") +JNIEnv* env, ${jteData.param} + @else +JNIEnv* env + @endif + @else + @if (jteData.param != "") +JNIEnv* env, jobject thiz, ${jteData.param} + @else +JNIEnv* env, jobject thiz + @endif + @endif +@else +${jteData.param} +@endif
\ No newline at end of file |
