28package com.jogamp.gluegen;
30import com.jogamp.gluegen.JavaConfiguration.JavaCallbackInfo;
31import com.jogamp.gluegen.cgram.types.Type;
33import java.nio.ByteBuffer;
38 final String setFuncSignature;
40 final String capIfaceName;
41 final String lowIfaceName;
42 final String lockInstanceName;
43 final String dataMapInstanceName;
44 final String dataInstanceName;
45 final String DataClassName;
46 final String fqUsrParamClassName;
48 final String jcbNextIDVarName;
50 final boolean userParamDefined;
52 final String setFuncCBArgName;
53 final Type setFuncUserParamCType;
54 final JavaType setFuncUserParamJType;
55 final String setFuncUserParamTypeName;
56 final String setFuncUserParamArgName;
57 final boolean userParamIsKey;
58 final boolean userParamIsCompound;
59 final boolean userParamIsMappedToID;
60 final String userParamIDMapInstanceName;
62 final String userParamClassName;
63 final boolean customKeyClass;
64 final String KeyClassName;
65 final boolean useDataMap;
70 this.setFuncSignature = setFuncSignature;
71 this.info = javaCallback;
75 lockInstanceName = lowIfaceName+
"Lock";
76 dataMapInstanceName = lowIfaceName+
"DataMap";
77 dataInstanceName = lowIfaceName+
"Data";
78 DataClassName = capIfaceName+
"Data";
79 fqUsrParamClassName = cfg.packageName()+
"."+cfg.className()+
"."+DataClassName;
81 jcbNextIDVarName =
"NEXT_"+capIfaceName+
"_ID";
83 setFuncCBArgName = binding.
getArgumentName(javaCallback.setFuncCBParamIdx);
85 userParamDefined = javaCallback.setFuncUserParamIdx >= 0;
86 if( !userParamDefined ) {
87 setFuncUserParamCType =
null;
88 setFuncUserParamJType =
null;
89 setFuncUserParamTypeName =
null;
90 setFuncUserParamArgName =
null;
92 userParamIsKey =
false;
94 setFuncUserParamCType = mb.
getCArgumentType(javaCallback.setFuncUserParamIdx);
96 setFuncUserParamTypeName = setFuncUserParamJType.
getName();
97 setFuncUserParamArgName = binding.
getArgumentName(javaCallback.setFuncUserParamIdx);
99 userParamIsKey = info.setFuncKeyIndices.contains(info.setFuncUserParamIdx);
101 if(
null != setFuncUserParamJType && !setFuncUserParamJType.
isLong() ) {
103 userParamIsCompound =
true;
104 userParamIsMappedToID =
false;
105 userParamIDMapInstanceName =
null;
107 userParamIsCompound =
false;
108 userParamIsMappedToID =
true;
109 userParamIDMapInstanceName = userParamIsKey ? lowIfaceName+
"UserObjIDMap" :
null;
112 userParamIsCompound =
false;
113 userParamIsMappedToID =
false;
114 userParamIDMapInstanceName =
null;
117 if( userParamDefined ) {
118 if( userParamIsCompound ) {
119 userParamClassName = setFuncUserParamTypeName;
120 }
else if(
null != javaCallback.userParamClassName ) {
121 userParamClassName = javaCallback.userParamClassName;
123 userParamClassName =
"Object";
126 userParamClassName =
null;
129 if(
null != javaCallback.customKeyClassName ) {
130 customKeyClass =
true;
131 KeyClassName = javaCallback.customKeyClassName;
134 customKeyClass =
false;
135 KeyClassName = capIfaceName+
"Key";
136 useDataMap = javaCallback.setFuncKeyIndices.size() > 0;
143 if( !customKeyClass && !info.keyClassEmitted ) {
144 emitJavaKeyClass(unit);
146 info.keyClassEmitted =
true;
148 emitJavaBriefAPIDoc(unit,
"Returns ",
"set of ",
"",
"for ");
149 unit.
emitln(
" public Set<"+KeyClassName+
"> get"+capIfaceName+
"Keys();");
151 emitJavaBriefAPIDoc(unit,
"Returns ",
"whether callback ",
"if callback ",
"is mapped for ");
152 unit.
emitln(
" public boolean is"+capIfaceName+
"Mapped("+KeyClassName+
" key);");
154 emitJavaBriefAPIDoc(unit,
"Returns "+info.cbFuncTypeName+
" callback ",
"mapped to ",
"",
"for ");
155 unit.
emitln(
" public "+info.cbFuncTypeName+
" get"+capIfaceName+
"("+KeyClassName+
" key);");
157 if( userParamDefined ) {
158 emitJavaBriefAPIDoc(unit,
"Returns user-param ",
"mapped to ",
"",
"for ");
159 unit.
emitln(
" public "+userParamClassName+
" get"+capIfaceName+
"UserParam("+KeyClassName+
" key);");
162 emitJavaBriefAPIDoc(unit,
"Releases all callback data ",
"mapped via ",
"",
"skipping toolkit API. Favor passing `null` callback ref to ");
163 unit.
emitln(
" public int releaseAll"+capIfaceName+
"();");
165 emitJavaBriefAPIDoc(unit,
"Releases callback data ",
"mapped to ",
"",
"skipping toolkit API. Favor passing `null` callback ref to ");
166 unit.
emitln(
" public void release"+capIfaceName+
"("+KeyClassName+
" key);");
169 emitJavaBriefAPIDoc(unit,
"Returns ",
"whether callback ",
"if callback ",
"is mapped for ");
170 unit.
emitln(
" public boolean is"+capIfaceName+
"Mapped();");
172 emitJavaBriefAPIDoc(unit,
"Returns "+info.cbFuncTypeName+
" callback ",
"mapped to ",
"",
"for ");
173 unit.
emitln(
" public "+info.cbFuncTypeName+
" get"+capIfaceName+
"();");
175 if( userParamDefined ) {
176 emitJavaBriefAPIDoc(unit,
"Returns user-param ",
"mapped to ",
"",
"for ");
177 unit.
emitln(
" public "+userParamClassName+
" get"+capIfaceName+
"UserParam();");
180 emitJavaBriefAPIDoc(unit,
"Releases callback data ",
"",
"",
"skipping toolkit API. Favor passing `null` callback ref to ");
181 unit.
emitln(
" public void release"+capIfaceName+
"();");
186 if( !customKeyClass && !info.keyClassEmitted ) {
187 emitJavaKeyClass(unit);
189 info.keyClassEmitted =
true;
191 emitJavaBriefAPIDoc(unit,
"Returns ",
"set of ",
"",
"for ");
192 unit.
emitln(
" public final Set<"+KeyClassName+
"> get"+capIfaceName+
"Keys() {");
193 unit.
emitln(
" synchronized( "+lockInstanceName+
" ) {");
194 unit.
emitln(
" return "+dataMapInstanceName+
".keySet();");
198 emitJavaBriefAPIDoc(unit,
"Returns ",
"whether callback ",
"if callback ",
"is mapped for ");
199 unit.
emitln(
" public final boolean is"+capIfaceName+
"Mapped("+KeyClassName+
" key) {");
200 unit.
emitln(
" synchronized( "+lockInstanceName+
" ) {");
201 unit.
emitln(
" return null != "+dataMapInstanceName+
".get(key);");
206 emitJavaBriefAPIDoc(unit,
"Returns "+info.cbFuncTypeName+
" callback ",
"mapped to ",
"",
"for ");
207 unit.
emitln(
" public final "+info.cbFuncTypeName+
" get"+capIfaceName+
"("+KeyClassName+
" key) {");
208 unit.
emitln(
" synchronized( "+lockInstanceName+
" ) {");
209 unit.
emitln(
" final "+DataClassName+
" value = "+dataMapInstanceName+
".get(key);");
210 unit.
emitln(
" return null != value ? value.func : null;");
215 if( userParamDefined ) {
216 emitJavaBriefAPIDoc(unit,
"Returns user-param ",
"mapped to ",
"",
"for ");
217 unit.
emitln(
" public final "+userParamClassName+
" get"+capIfaceName+
"UserParam("+KeyClassName+
" key) {");
218 unit.
emitln(
" synchronized( "+lockInstanceName+
" ) {");
219 unit.
emitln(
" final "+DataClassName+
" value = "+dataMapInstanceName+
".get(key);");
220 unit.
emitln(
" return null != value ? value.param : null;");
225 emitJavaBriefAPIDoc(unit,
"Releases all callback data ",
"mapped via ",
"",
"skipping toolkit API. Favor passing `null` callback ref to ");
226 unit.
emitln(
" public final int releaseAll"+capIfaceName+
"() {");
227 unit.
emitln(
" synchronized( "+lockInstanceName+
" ) {");
228 unit.
emitln(
" final Set<"+KeyClassName+
"> keySet = "+dataMapInstanceName+
".keySet();");
229 unit.
emitln(
" final "+KeyClassName+
"[] keys = keySet.toArray(new "+KeyClassName+
"[keySet.size()]);");
230 unit.
emitln(
" for(int i=0; i<keys.length; ++i) {");
231 unit.
emitln(
" final "+KeyClassName+
" key = keys[i];");
232 unit.
emitln(
" release"+capIfaceName+
"(key);");
234 unit.
emitln(
" return keys.length;");
238 emitJavaBriefAPIDoc(unit,
"Releases callback data ",
"mapped to ",
"",
"skipping toolkit API. Favor passing `null` callback ref to ");
239 unit.
emitln(
" public final void release"+capIfaceName+
"("+KeyClassName+
" key) {");
240 unit.
emitln(
" synchronized( "+lockInstanceName+
" ) {");
241 if( userParamIsMappedToID && userParamIsKey ) {
242 unit.
emitln(
" "+DataClassName+
" value = "+dataMapInstanceName+
".remove(key);");
243 unit.
emitln(
" if( null != value ) {");
244 unit.
emitln(
" "+userParamIDMapInstanceName+
".remove(value.paramID);");
247 unit.
emitln(
" /* "+DataClassName+
" value = */ "+dataMapInstanceName+
".remove(key);");
253 emitJavaBriefAPIDoc(unit,
"Returns ",
"whether callback ",
"if callback ",
"is mapped for ");
254 unit.
emitln(
" public final boolean is"+capIfaceName+
"Mapped() {");
255 unit.
emitln(
" synchronized( "+lockInstanceName+
" ) {");
256 unit.
emitln(
" return null != "+dataInstanceName+
";");
261 emitJavaBriefAPIDoc(unit,
"Returns "+info.cbFuncTypeName+
" callback ",
"mapped to ",
"",
"for ");
262 unit.
emitln(
" public final "+info.cbFuncTypeName+
" get"+capIfaceName+
"() {");
263 unit.
emitln(
" synchronized( "+lockInstanceName+
" ) {");
264 unit.
emitln(
" final "+DataClassName+
" value = "+dataInstanceName+
";");
265 unit.
emitln(
" return null != value ? value.func : null;");
270 if( userParamDefined ) {
271 emitJavaBriefAPIDoc(unit,
"Returns user-param ",
"mapped to ",
"",
"for ");
272 unit.
emitln(
" public final "+userParamClassName+
" get"+capIfaceName+
"UserParam() {");
273 unit.
emitln(
" synchronized( "+lockInstanceName+
" ) {");
274 unit.
emitln(
" final "+DataClassName+
" value = "+dataInstanceName+
";");
275 unit.
emitln(
" return null != value ? value.param : null;");
281 emitJavaBriefAPIDoc(unit,
"Releases callback data ",
"",
"",
"skipping toolkit API. Favor passing `null` callback ref to ");
282 unit.
emitln(
" public final void release"+capIfaceName+
"() {");
283 unit.
emitln(
" synchronized( "+lockInstanceName+
" ) {");
284 unit.
emitln(
" // final "+DataClassName+
" value = "+dataInstanceName+
";");
285 if( userParamIsMappedToID && userParamIsKey ) {
286 unit.
emitln(
" "+userParamIDMapInstanceName+
".remove(dataInstanceName.paramID);");
288 unit.
emitln(
" "+dataInstanceName+
" = null;");
293 unit.
emitln(
" private final void add"+capIfaceName+
"("+binding.
getJavaSelectParameter(
new StringBuilder(), info.setFuncKeyIndices,
true).toString()+DataClassName+
" value) {");
295 unit.
emitln(
" final "+KeyClassName+
" key = new "+KeyClassName+
"("+binding.
getJavaCallSelectArguments(
new StringBuilder(), info.setFuncKeyIndices,
false).toString()+
");");
296 if( userParamIsMappedToID && userParamIsKey ) {
297 unit.
emitln(
" final "+DataClassName+
" old = "+dataMapInstanceName+
".put(key, value);");
299 unit.
emitln(
" /* final "+DataClassName+
" old = */ "+dataMapInstanceName+
".put(key, value);");
302 if( userParamIsMappedToID && userParamIsKey ) {
303 unit.
emitln(
" final "+DataClassName+
" old = "+dataInstanceName+
";");
305 unit.
emitln(
" // final "+DataClassName+
" old = "+dataInstanceName+
";");
307 unit.
emitln(
" "+dataInstanceName+
" = value;");
309 if( userParamIsMappedToID && userParamIsKey ) {
310 unit.
emitln(
" if( null != old ) {");
311 unit.
emitln(
" "+userParamIDMapInstanceName+
".remove(old.paramID);");
313 unit.
emitln(
" if( null != value.param ) {");
314 unit.
emitln(
" "+userParamIDMapInstanceName+
".put(value.paramID, value.param);");
319 if( !cfg.emittedJavaCallbackUserParamClasses.contains(fqUsrParamClassName) ) {
320 emitJavaDataClass(unit);
321 cfg.emittedJavaCallbackUserParamClasses.add(fqUsrParamClassName);
324 unit.
emitln(
" private static final Map<"+KeyClassName+
", "+DataClassName+
"> "+dataMapInstanceName+
" = new HashMap<"+KeyClassName+
", "+DataClassName+
">();");
326 unit.
emitln(
" private static "+DataClassName+
" "+dataInstanceName+
" = null;");
328 if( userParamIsMappedToID && userParamIsKey ) {
329 unit.
emitln(
" private static final LongObjectHashMap "+userParamIDMapInstanceName+
" = new LongObjectHashMap();");
331 unit.
emitln(
" private static long "+jcbNextIDVarName+
" = 1;");
332 unit.
emitln(
" private static final Object "+lockInstanceName+
" = new Object();");
334 emitJavaStaticCallback(unit);
338 private final void emitJavaBriefAPIDoc(
final CodeUnit unit,
final String actionText,
final String relationToKey,
final String noKeyText,
final String relationToFunc) {
339 unit.
emit(
" /** "+actionText);
340 if( info.setFuncKeyIndices.size() > 0 ) {
341 unit.
emit(relationToKey);
344 unit.
emit(noKeyText);
346 unit.
emit(relationToFunc);
347 unit.
emitln(
"<br> <code>"+setFuncSignature+
"</code> */");
350 private final void emitJavaKeyClass(
final CodeUnit unit) {
353 emitJavaBriefAPIDoc(unit,
"",
"",
"",
"for ");
354 unit.emitln(
" public static class "+KeyClassName+
" {");
355 binding.
forEachParameter( (
final int idx,
final int consumedCount,
final Type cType,
final JavaType jType,
final String name ) -> {
356 if( !cType.isVoid() && info.setFuncKeyIndices.contains(idx) ) {
357 unit.emitln(
" public final "+jType+
" "+name+
";");
363 unit.emitln(
" public "+KeyClassName+
"("+binding.
getJavaSelectParameter(
new StringBuilder(), info.setFuncKeyIndices,
false).toString()+
") {");
364 binding.
forEachParameter( (
final int idx,
final int consumedCount,
final Type cType,
final JavaType jType,
final String name ) -> {
365 if( !cType.isVoid() && info.setFuncKeyIndices.contains(idx) ) {
366 unit.emitln(
" this."+name+
" = "+name+
";");
373 unit.emitln(
" @Override");
374 unit.emitln(
" public boolean equals(final Object o) {");
375 unit.emitln(
" if( this == o ) {");
376 unit.emitln(
" return true;");
378 unit.emitln(
" if( !(o instanceof "+KeyClassName+
") ) {");
379 unit.emitln(
" return false;");
382 final int count = binding.
forEachParameter( (
final int idx,
final int consumedCount,
final Type cType,
final JavaType jType,
final String name ) -> {
383 if( !cType.isVoid() && info.setFuncKeyIndices.contains(idx) ) {
384 if( 0 == consumedCount ) {
385 unit.emitln(
" final "+KeyClassName+
" o2 = ("+KeyClassName+
")o;");
386 unit.emit (
" return ");
391 if( jType.isCompoundTypeWrapper() ) {
392 unit.emit(name+
".getDirectBufferAddress() == o2."+name+
".getDirectBufferAddress()");
393 }
else if( jType.isPrimitive() || idx == info.setFuncUserParamIdx ) {
394 unit.emit(name+
" == o2."+name);
396 unit.emit(name+
".equals( o2."+name+
" )");
404 unit.emit(
" return true");
409 unit.emitln(
" @Override");
410 unit.emitln(
" public int hashCode() {");
412 final int count = binding.
forEachParameter( (
final int idx,
final int consumedCount,
final Type cType,
final JavaType jType,
final String name ) -> {
413 if( !cType.isVoid() && info.setFuncKeyIndices.contains(idx) ) {
414 if( 0 == consumedCount ) {
415 unit.emitln(
" // 31 * x == (x << 5) - x");
416 unit.emit (
" int hash = ");
418 unit.emit (
" hash = ((hash << 5) - hash) + ");
420 if( jType.isPrimitive() ) {
421 if( jType.isLong() ) {
422 unit.emitln(
"HashUtil.getAddrHash32_EqualDist( "+name+
" );");
424 unit.emitln(name+
";");
426 }
else if( jType.isCompoundTypeWrapper() ) {
427 unit.emitln(
"HashUtil.getAddrHash32_EqualDist( "+name+
".getDirectBufferAddress() );");
429 if( idx == info.setFuncUserParamIdx ) {
430 unit.emitln(
"System.identityHashCode( "+name+
" );");
432 unit.emitln(name+
".hashCode();");
441 unit.emitln(
" return 0;");
443 unit.emitln(
" return hash;");
450 private final void emitJavaDataClass(
final CodeUnit unit) {
451 unit.emitln(
" private static class "+DataClassName+
" {");
452 unit.emitln(
" final " + info.cbFuncTypeName +
" func;");
453 if( userParamDefined ) {
454 unit.emitln(
" // userParamArgCType "+setFuncUserParamCType);
455 unit.emitln(
" // userParamArgJType "+setFuncUserParamJType);
456 unit.emitln(
" final "+setFuncUserParamTypeName+
" param;");
457 if( userParamIsMappedToID ) {
458 unit.emitln(
" final long paramID;");
461 unit.emitln(
" // No user param defined.");
463 unit.emit (
" "+DataClassName+
"(final "+info.cbFuncTypeName+
" func");
464 if( userParamDefined ) {
465 if( userParamIsMappedToID ) {
466 unit.emit(
", final long paramID");
468 unit.emit(
", final "+setFuncUserParamTypeName+
" param");
471 unit.emitln(
" this.func = func;");
472 if( userParamDefined ) {
473 if( userParamIsMappedToID ) {
474 unit.emitln(
" this.paramID = paramID;");
476 unit.emitln(
" this.param = param;");
483 final StringBuilder buf =
new StringBuilder();
485 info.cbFuncBinding.
forEachParameter( (
final int idx,
final int consumedCount,
final Type cType,
final JavaType jType,
final String name ) -> {
487 if( idx == info.cbFuncUserParamIdx ) {
490 buf.append(jType.getDescriptor(cfg));
499 return buf.toString();
503 buf.append(
"Class<?> staticCBClazz, String callbackSignature");
504 if( !userParamDefined ) {
507 buf.append(
", long nativeUserParam");
511 buf.append(
"this.getClass(), \"" + getJavaStaticCallbackSignature() +
"\"");
512 if( !userParamDefined ) {
515 buf.append(
", nativeUserParam");
520 if( userParamDefined ) {
521 unit.
emitln(
" final long nativeUserParam;");
523 unit.
emitln(
" synchronized( "+lockInstanceName+
" ) {");
524 if( userParamDefined ) {
525 if( setFuncUserParamJType.
isLong() ) {
526 unit.
emitln(
" nativeUserParam = "+setFuncUserParamArgName+
";");
528 unit.
emitln(
" if( null != "+setFuncUserParamArgName+
" ) {");
531 unit.
emitln(
" nativeUserParam = "+setFuncUserParamArgName+
".getDirectBufferAddress();");
534 unit.
emitln(
" nativeUserParam = "+jcbNextIDVarName+
"++;");
535 unit.
emitln(
" if( 0 >= "+jcbNextIDVarName+
" ) { "+jcbNextIDVarName+
" = 1; }");
538 unit.
emitln(
" nativeUserParam = 0;");
542 unit.
emitln(
" if( null != "+setFuncCBArgName+
" ) {");
543 unit.emit (
" add"+capIfaceName+
"("+binding.
getJavaCallSelectArguments(
new StringBuilder(), info.setFuncKeyIndices,
true).toString()+
544 "new "+DataClassName+
"("+setFuncCBArgName);
545 if( userParamDefined ) {
546 if( userParamIsMappedToID ) {
547 unit.
emit(
", nativeUserParam");
549 unit.
emit(
", "+setFuncUserParamArgName);
552 unit.
emitln(
" } else { ");
553 unit.
emitln(
" // release a previously mapped instance ");
555 unit.
emitln(
" release"+capIfaceName+
"( new "+KeyClassName+
"( "+binding.
getJavaCallSelectArguments(
new StringBuilder(), info.setFuncKeyIndices,
false).toString()+
" ) );");
557 unit.
emitln(
" release"+capIfaceName+
"();");
560 unit.
emitln(
" } // synchronized ");
564 private final void emitJavaStaticCallback(
final CodeUnit unit) {
565 unit.
emitln(
" /** Static callback invocation, dispatching to "+info.cbSimpleClazzName+
" for callback <br> <code>"+
566 info.cbFuncType.
toString(info.cbFuncTypeName,
false,
true)+
"</code> */");
567 unit.emit (
" /* pp */ static "+cbFuncJavaReturnType.
getName()+
" invoke"+capIfaceName+
"(");
568 final boolean[] mapNativePtrToCompound = {
false };
569 final JavaType[] origUserParamJType = {
null };
570 info.cbFuncBinding.
forEachParameter( (
final int idx,
final int consumedCount,
final Type cType,
final JavaType jType,
final String name ) -> {
571 if( !cType.isVoid() && !jType.isPascalLen() ) {
572 if( 0 < consumedCount ) { unit.
emit(
", "); }
573 if( idx == info.cbFuncUserParamIdx ) {
574 unit.
emit(
"long nativeUserParam");
575 if( jType.isCompoundTypeWrapper() ) {
576 mapNativePtrToCompound[0] =
true;
577 origUserParamJType[0] = jType;
580 unit.
emit(jType+
" "+name);
588 final boolean useParamLocal[] = {
false };
589 if( userParamDefined ) {
590 if( mapNativePtrToCompound[0] ) {
591 unit.
emitln(
" final "+origUserParamJType[0]+
" "+info.cbFuncUserParamName+
" = "+origUserParamJType[0]+
".derefPointer(nativeUserParam);");
592 useParamLocal[0] =
true;
593 }
else if( userParamIsMappedToID && userParamIsKey ) {
594 unit.
emitln(
" final "+userParamClassName+
" "+info.cbFuncUserParamName+
";");
597 unit.
emitln(
" final "+DataClassName+
" value;");
598 unit.
emitln(
" synchronized( "+lockInstanceName+
" ) {");
599 if( userParamDefined ) {
600 if( userParamIsMappedToID && userParamIsKey && !mapNativePtrToCompound[0] ) {
601 unit.
emitln(
" "+info.cbFuncUserParamName+
" = ("+userParamClassName+
") "+userParamIDMapInstanceName+
".get(nativeUserParam);");
602 useParamLocal[0] =
true;
606 unit.
emitln(
" final "+KeyClassName+
" key = new "+KeyClassName+
"("+info.cbFuncBinding.
getJavaCallSelectArguments(
new StringBuilder(), info.cbFuncKeyIndices,
false).toString()+
");");
607 unit.
emitln(
" value = "+dataMapInstanceName+
".get(key);");
609 unit.
emitln(
" value = "+dataInstanceName+
";");
612 unit.
emitln(
" if( null == value ) {");
613 if( !cbFuncJavaReturnType.
isVoid() ) {
614 unit.
emitln(
" return 0;");
619 if( !cbFuncJavaReturnType.
isVoid() ) {
620 unit.
emit(
" return ");
624 unit.
emit(
"value.func.callback(");
625 info.cbFuncBinding.
forEachParameter( (
final int idx,
final int consumedCount,
final Type cType,
final JavaType jType,
final String name ) -> {
626 if( !cType.isVoid() && !jType.isPascalLen() ) {
627 if( 0 < consumedCount ) { unit.
emit(
", "); }
628 if( idx == info.cbFuncUserParamIdx && !useParamLocal[0] ) {
629 unit.
emit(
"value.param");
648 buf.append(
", jclass staticCBClazz, jstring jcallbackSignature");
649 if( !userParamDefined ) {
652 buf.append(
", jlong jnativeUserParam");
657 if( ( argIdx == info.setFuncCBParamIdx || argIdx == info.setFuncUserParamIdx ) ) {
658 unit.
emit(
"_native");
665 if( userParamDefined ) {
672 final String jcbFriendlyBasename = info.setFuncName+
"("+info.cbSimpleClazzName+
")";
673 final String staticBindingMethodName =
"invoke"+jcbNativeBasename;
674 final String staticBindingClazzVarName =
"staticCBClazz"+jcbNativeBasename;
675 final String staticBindingMethodIDVarName =
"staticCBMethod"+jcbNativeBasename;
676 final String cbFuncArgName = binding.
getArgumentName(info.setFuncCBParamIdx);
677 final String nativeCBFuncVarName = cbFuncArgName+
"_native";
678 final String userParamTypeName, nativeUserParamVarName;
679 if( userParamDefined ) {
680 userParamTypeName = info.cbFuncUserParamType.
getCName();
681 nativeUserParamVarName = binding.
getArgumentName(info.setFuncUserParamIdx)+
"_native";
683 userParamTypeName =
null;
684 nativeUserParamVarName =
null;
687 unit.
emitln(
" // JavaCallback handling");
688 unit.
emitln(
" if( NULL == staticCBClazz ) { (*env)->FatalError(env, \"NULL staticCBClazz passed to '"+jcbFriendlyBasename+
"'\"); }");
689 unit.
emitln(
" "+info.cbFuncTypeName+
" "+nativeCBFuncVarName+
";");
690 if( userParamDefined ) {
691 unit.
emitln(
" "+userParamTypeName+
"* "+nativeUserParamVarName+
";");
693 unit.
emitln(
" if( NULL != "+cbFuncArgName+
" ) {");
694 unit.
emitln(
" if( NULL == "+staticBindingClazzVarName+
" || NULL == "+staticBindingMethodIDVarName+
" ) {");
695 unit.
emitln(
" jclass staticCBClazz2 = (*env)->NewGlobalRef(env, staticCBClazz);");
696 unit.
emitln(
" if( NULL == staticCBClazz2 ) { (*env)->FatalError(env, \"Failed NewGlobalRef(staticCBClazz) in '"+jcbFriendlyBasename+
"'\"); }");
697 unit.
emitln(
" const char* callbackSignature = (*env)->GetStringUTFChars(env, jcallbackSignature, (jboolean*)NULL);");
698 unit.
emitln(
" if( NULL == callbackSignature ) { (*env)->FatalError(env, \"Failed callbackSignature in '"+jcbFriendlyBasename+
"'\"); }");
699 unit.
emitln(
" jmethodID cbMethodID = (*env)->GetStaticMethodID(env, staticCBClazz2, \""+staticBindingMethodName+
"\", callbackSignature);");
700 unit.
emitln(
" if( NULL == cbMethodID ) {");
701 unit.
emitln(
" char cmsg[400];");
702 unit.
emitln(
" snprintf(cmsg, 400, \"Failed GetStaticMethodID of '"+staticBindingMethodName+
"(%s)' in '"+jcbFriendlyBasename+
"'\", callbackSignature);");
703 unit.
emitln(
" (*env)->FatalError(env, cmsg);");
705 unit.
emitln(
" (*env)->ReleaseStringUTFChars(env, jcallbackSignature, callbackSignature);");
706 unit.
emitln(
" "+staticBindingClazzVarName+
" = staticCBClazz2;");
707 unit.
emitln(
" "+staticBindingMethodIDVarName+
" = cbMethodID;");
714 final String staticBindingClazzArgVarName =
"staticCBArg" + baseArgName +
"Clazz"+jcbNativeBasename;
715 final String staticBindingMethodIDArgVarName =
"staticCBArg" + baseArgName +
"Method"+jcbNativeBasename;
716 unit.
emitln(
" if( NULL == "+staticBindingClazzArgVarName+
" || NULL == "+staticBindingMethodIDArgVarName+
" ) {");
717 final String argClassDescriptor = currentJavaType.
getDescriptor(cfg);
718 final String argClassRef = currentJavaType.
getName(cfg);
719 final String argClassLocation = argClassRef.replace(
".",
"/");
720 unit.
emitln(
" jclass "+staticBindingClazzArgVarName+
"2 = (*env)->FindClass(env, \""+argClassLocation+
"\");");
721 unit.
emitln(
" if( NULL == "+staticBindingClazzArgVarName+
"2 ) { (*env)->FatalError(env, \"Failed FindClass("+argClassLocation+
") in '"+jcbFriendlyBasename+
"'\"); }");
722 unit.
emitln(
" jmethodID "+staticBindingMethodIDArgVarName+
"2 = (*env)->GetStaticMethodID(env, "+staticBindingClazzArgVarName+
"2, \"create\", \"("+bbjt.
getDescriptor()+
")"+argClassDescriptor+
"\");");
723 unit.
emitln(
" if( NULL == "+staticBindingMethodIDArgVarName+
"2 ) {");
724 unit.
emitln(
" char cmsg[400];");
725 unit.
emitln(
" snprintf(cmsg, 400, \"Failed GetStaticMethodID of '"+argClassRef+
".create("+bbjt.
getDescriptor()+
")"+argClassDescriptor+
" in "+jcbFriendlyBasename+
"'\");");
726 unit.
emitln(
" (*env)->FatalError(env, cmsg);");
728 unit.
emitln(
" "+staticBindingClazzArgVarName+
" = "+staticBindingClazzArgVarName+
"2;");
729 unit.
emitln(
" "+staticBindingMethodIDArgVarName+
" = "+staticBindingMethodIDArgVarName+
"2;");
733 unit.
emitln(
" "+nativeCBFuncVarName+
" = func"+jcbNativeBasename+
";");
734 if( userParamDefined ) {
735 unit.
emitln(
" "+nativeUserParamVarName+
" = ("+userParamTypeName+
"*) jnativeUserParam;");
738 unit.
emitln(
" "+nativeCBFuncVarName+
" = NULL;");
739 if( userParamDefined ) {
740 unit.
emitln(
" "+nativeUserParamVarName+
" = NULL;");
754 final String jcbFriendlyBasename = info.setFuncName+
"("+info.cbSimpleClazzName+
")";
755 final String staticBindingClazzVarName =
"staticCBClazz"+jcbNativeBasename;
756 final String staticBindingMethodIDVarName =
"staticCBMethod"+jcbNativeBasename;
757 final String staticCallbackName =
"func"+jcbNativeBasename;
758 final String userParamTypeName, userParamArgName;
759 if( userParamDefined ) {
761 userParamTypeName = info.cbFuncUserParamType.
getCName();
762 userParamArgName = info.cbFuncBinding.
getArgumentName(info.cbFuncUserParamIdx);
764 userParamTypeName =
null;
765 userParamArgName =
null;
770 unit.
emitln(
"static jclass "+staticBindingClazzVarName+
" = NULL;");
771 unit.
emitln(
"static jmethodID "+staticBindingMethodIDVarName+
" = NULL;");
776 final String staticBindingClazzArgVarName =
"staticCBArg" + baseArgName +
"Clazz"+jcbNativeBasename;
777 final String staticBindingMethodIDArgVarName =
"staticCBArg" + baseArgName +
"Method"+jcbNativeBasename;
778 unit.
emitln(
"static jclass "+staticBindingClazzArgVarName+
" = NULL;");
779 unit.
emitln(
"static jmethodID "+staticBindingMethodIDArgVarName+
" = NULL;");
784 unit.
emit(
"static "+cReturnType.
getCName()+
" "+staticCallbackName+
"(");
790 unit.
emitln(
" int detachJVM = 0;");
791 unit.
emitln(
" JNIEnv* env = JVMUtil_GetJNIEnv(1 /* daemon */, &detachJVM);");
792 unit.
emitln(
" jclass cbClazz = "+staticBindingClazzVarName+
";");
793 unit.
emitln(
" jmethodID cbMethod = "+staticBindingMethodIDVarName+
";");
798 final String staticBindingClazzArgVarName =
"staticCBArg" + baseArgName +
"Clazz"+jcbNativeBasename;
799 final String staticBindingMethodIDArgVarName =
"staticCBArg" + baseArgName +
"Method"+jcbNativeBasename;
800 unit.
emitln(
" jclass cbClazzArg" + baseArgName+
" = "+staticBindingClazzArgVarName+
";");
801 unit.
emitln(
" jmethodID cbMethodArg" + baseArgName+
" = "+staticBindingMethodIDArgVarName+
";");
804 unit.
emitln(
" if( NULL == env || NULL == cbClazz || NULL == cbMethod ) {");
805 if( !cReturnType.
isVoid() ) {
806 unit.
emitln(
" return 0;");
814 emitJavaCallbackBodyCToJavaPreCall(jcbFuncCMethodEmitter);
817 if( userParamDefined ) {
818 unit.
emitln(
" "+userParamTypeName+
"* "+userParamArgName+
"_jni = ("+userParamTypeName+
"*) "+userParamArgName+
";");
820 unit.
emitln(
" // C Params: "+info.cbFuncBinding.
getCParameterList(
new StringBuilder(),
false,
null).toString());
823 final String returnStatement;
824 if( !cReturnType.
isVoid() ) {
826 returnStatement =
"return _res;";
828 returnStatement =
"return;";
830 if( !cReturnType.
isVoid() ) {
837 emitCBodyPassArguments(unit);
839 unit.
emitln(
" if( (*env)->ExceptionCheck(env) ) {");
840 unit.
emitln(
" fprintf(stderr, \"Info: Callback '"+jcbFriendlyBasename+
"': Exception in Java Callback caught:\\n\");");
841 unit.
emitln(
" (*env)->ExceptionDescribe(env);");
842 unit.
emitln(
" (*env)->ExceptionClear(env);");
848 unit.
emitln(
" JVMUtil_ReleaseJNIEnv(env, detachJVM);");
849 unit.
emitln(
" "+returnStatement);
858 if( i == info.cbFuncUserParamIdx ) {
868 private int emitCBodyPassArguments(
final CodeUnit unit) {
870 boolean needsComma =
false;
873 if( !currentJavaType.isPascalLen() ) {
879 if( i != info.cbFuncUserParamIdx && currentJavaType.isCompoundTypeWrapper() ) {
880 final String cBaseArgName = CodeGenUtils.capitalizeString( baseArgName );
881 final String jniArgName = baseArgName +
"_jni";
882 unit.emit( jniArgName +
" != NULL ? " +
"(*env)->CallStaticObjectMethod(env, cbClazzArg" + cBaseArgName +
", cbMethodArg" + cBaseArgName +
", " + jniArgName +
") : NULL" );
884 unit.emit( baseArgName +
"_jni" );
Emits the C-side component of the Java<->C JNI binding to its CodeUnit, see FunctionEmitter.
boolean emitBodyMapCToJNIType(final int argIdx, final boolean addLocalVar)
Emit code, converting a C type into a java JNI-type.
static String decapitalizeString(final String string)
Converts first letter to lower case.
static String capitalizeString(final String string)
Converts first letter to upper case.
General code unit (a generated C or Java source file), covering multiple FunctionEmitter allowing to ...
void emit(final String s)
final MethodBinding binding
void emitCAdditionalCode(final CodeUnit unit, final CMethodBindingEmitter jcbFuncCMethodEmitter)
Emit addition C code, i.e.
final String getJavaStaticCallbackSignature()
void appendCAdditionalJNIDescriptor(final StringBuilder buf)
void emitJavaSetFuncPreCall(final CodeUnit unit)
final int appendJavaAdditionalJNIParameter(final StringBuilder buf)
void emitJavaAdditionalCode(final CodeUnit unit, final boolean isInterface)
JavaCallbackEmitter(final JavaConfiguration cfg, final MethodBinding mb, final JavaCallbackInfo javaCallback, final String setFuncSignature)
final int appendJavaAdditionalJNIArguments(final StringBuilder buf)
void emitCSetFuncPreCall(final CodeUnit unit)
void emitCOptArgumentSuffix(final CodeUnit unit, final int argIdx)
int appendCAdditionalParameter(final StringBuilder buf)
JavaCallback compile time information, produced by JavaEmitter#beginFunctions(TypeDictionary,...
Parses and provides access to the contents of .cfg files for the JavaEmitter.
final boolean shouldIgnoreInInterface(final String symbol)
Variant of shouldIgnoreInInterface(AliasedSymbol), where this method only considers the current-name ...
Describes a java-side representation of a type that is used to represent the same data on both the Ja...
static StringBuilder appendJNIDescriptor(final StringBuilder res, final Class<?> c, final boolean useTrueType)
Appends the native (JNI) method-name descriptor corresponding to the given Class<?...
String getName()
Returns the Java type name corresponding to this type.
boolean isCompoundTypeWrapper()
static JavaType createForClass(final Class<?> clazz)
Creates a JavaType corresponding to the given Java type.
String getDescriptor()
Returns the descriptor (internal type signature) corresponding to this type.
Represents the binding of a C function to a Java method.
Type getCArgumentType(final int i)
String getArgumentName(final int i)
Returns either the argument name specified by the underlying FunctionSymbol or a fabricated argument ...
StringBuilder getJavaCallSelectArguments(final StringBuilder buf, final List< Integer > include, final boolean addTailSeparator)
int forEachParameter(final ParameterConsumer c)
StringBuilder getJavaParameterList(final StringBuilder buf)
Returns the function parameter list, i.e.
StringBuilder getJavaSelectParameter(final StringBuilder buf, final List< Integer > include, final boolean addTailSeparator)
Returns the function parameter list, i.e.
JavaType getJavaArgumentType(final int i)
JavaType getJavaReturnType()
String getInterfaceName()
Returns the FunctionSymbol's current aliased API name for the interface.
StringBuilder getCParameterList(final StringBuilder buf, final boolean useTypedef, final String callingConvention)
Returns the function parameter list, i.e.
String toString()
Returns a string representation of this type.
final String getCName()
Returns the name of this type.
final boolean isVoid()
Indicates whether this is a VoidType.