GlueGen v2.6.0-rc-20250712
GlueGen, Native Binding Generator for Java™ (public API).
ProcAddressCMethodBindingEmitter.java
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-2023 JogAmp Community. All rights reserved.
3 * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * - Redistribution of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * - Redistribution in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * Neither the name of Sun Microsystems, Inc. or the names of
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * This software is provided "AS IS," without a warranty of any kind. ALL
21 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
22 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
23 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
24 * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
25 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
26 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
27 * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
28 * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
29 * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
30 * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
31 * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
32 *
33 * You acknowledge that this software is not designed or intended for use
34 * in the design, construction, operation or maintenance of any nuclear
35 * facility.
36 *
37 * Sun gratefully acknowledges that this software was originally authored
38 * and developed by Kenneth Bradley Russell and Christopher John Kline.
39 */
40
41package com.jogamp.gluegen.procaddress;
42
43import com.jogamp.gluegen.CMethodBindingEmitter;
44import com.jogamp.gluegen.JavaType;
45import com.jogamp.gluegen.MethodBinding;
46import com.jogamp.gluegen.cgram.types.FunctionSymbol;
47import com.jogamp.gluegen.cgram.types.PointerType;
48import com.jogamp.gluegen.cgram.types.Type;
49
51
52 private boolean callThroughProcAddress;
53 private boolean hasProcAddrTypedef;
54
55 private String localTypedefCallingConvention;
56
57 private static final String procAddressJavaTypeName = JavaType.createForClass(Long.TYPE).jniTypeName();
58 private ProcAddressEmitter emitter;
59
61 final boolean callThroughProcAddress,
62 final boolean hasProcAddrTypedef,
63 final String localTypedefCallingConvention,
64 final ProcAddressEmitter emitter) {
65
66 super(
67 new MethodBinding(methodToWrap.getBinding()) {
68 @Override
69 public String getImplName() {
70 if (callThroughProcAddress) {
71 return ProcAddressEmitter.WRAP_PREFIX + super.getImplName();
72 } else {
73 return super.getImplName();
74 }
75 }
76 },
77 methodToWrap.getUnit(),
78 methodToWrap.getJavaPackageName(),
79 methodToWrap.getJavaClassName(),
80 methodToWrap.getIsOverloadedBinding(),
81 methodToWrap.getIsJavaMethodStatic(),
82 true,
83 methodToWrap.forIndirectBufferAndArrayImplementation(),
84 methodToWrap.getMachineDataInfo(),
85 emitter.getConfig()
86 );
87 if (methodToWrap.getReturnValueCapacityExpression() != null) {
88 setReturnValueCapacityExpression(methodToWrap.getReturnValueCapacityExpression());
89 }
90 if (methodToWrap.getReturnValueLengthExpression() != null) {
91 setReturnValueLengthExpression(methodToWrap.getReturnValueLengthExpression());
92 }
93 setTemporaryCVariableDeclarations(methodToWrap.getTemporaryCVariableDeclarations());
94 setTemporaryCVariableAssignments(methodToWrap.getTemporaryCVariableAssignments());
95
97
98 this.callThroughProcAddress = callThroughProcAddress;
99 this.hasProcAddrTypedef = hasProcAddrTypedef;
100 this.localTypedefCallingConvention = localTypedefCallingConvention;
101 this.emitter = emitter;
102 }
103
104 @Override
105 protected int appendArguments(final StringBuilder buf) {
106 int numEmitted = super.appendArguments(buf);
107 if (callThroughProcAddress) {
108 if (numEmitted > 0) {
109 buf.append(", ");
110 }
111 buf.append(procAddressJavaTypeName);
112 buf.append(" procAddress");
113 ++numEmitted;
114 }
115 return numEmitted;
116 }
117
118 @Override
120 if (callThroughProcAddress) {
121 // create variable for the function pointer with the right type, and set
122 // it to the value of the passed-in proc address
123 final FunctionSymbol cSym = binding.getCSymbol();
124
125 // Always emit the local typedef, based on our parsing results.
126 // In case we do have the public typedef from the original header,
127 // we use it for the local var and assign our proc-handle to it,
128 // cast to the local typedef.
129 // This allows the native C compiler to validate our types!
130 final String funcPointerTypedefBaseName = emitter.getFunctionPointerTypedefName(cSym);
131 final String funcPointerTypedefLocalName = "_local_" + funcPointerTypedefBaseName;
132 final String funcPointerTypedefName;
133 if (hasProcAddrTypedef) {
134 funcPointerTypedefName = funcPointerTypedefBaseName;
135 } else {
136 funcPointerTypedefName = funcPointerTypedefLocalName;
137 }
138 final PointerType funcPtrType = new PointerType(null, cSym.getType(), 0);
139
140 unit.emit(" typedef ");
141 unit.emit(funcPtrType.toString(funcPointerTypedefLocalName, localTypedefCallingConvention));
142 unit.emitln(";");
143
144 unit.emit(" ");
145 unit.emit(funcPointerTypedefName); // Uses public typedef if available!
146 unit.emit(" ptr_");
147 unit.emit(getNativeName());
148 unit.emitln(";");
149 }
150
151 super.emitBodyVariableDeclarations();
152 }
153
154 @Override
156 super.emitBodyVariablePreCallSetup();
157
158 if (callThroughProcAddress) {
159 // set the function pointer to the value of the passed-in procAddress
160 // See above notes in emitBodyVariableDeclarations(..)!
161 final String funcPointerTypedefBaseName = emitter.getFunctionPointerTypedefName(binding.getCSymbol());
162 final String funcPointerTypedefLocalName = "_local_" + funcPointerTypedefBaseName;
163 final String funcPointerTypedefName;
164 if (hasProcAddrTypedef) {
165 funcPointerTypedefName = funcPointerTypedefBaseName;
166 } else {
167 funcPointerTypedefName = funcPointerTypedefLocalName;
168 }
169
170 final String ptrVarName = "ptr_" + getNativeName();
171
172 if (hasProcAddrTypedef) {
173 unit.emitln(" // implicit type validation of "+funcPointerTypedefLocalName+" -> "+funcPointerTypedefName);
174 }
175 unit.emit(" ");
176 unit.emit(ptrVarName);
177 unit.emit(" = (");
178 unit.emit(funcPointerTypedefLocalName);
179 unit.emitln(") (intptr_t) procAddress;");
180
181 unit.emitln(" assert(" + ptrVarName + " != NULL);");
182 }
183 }
184
185 @Override
186 protected void emitBodyCallCFunction() {
187 if (!callThroughProcAddress) {
188 super.emitBodyCallCFunction();
189 } else {
190 // Make the call to the actual C function
191 unit.emit(" ");
192
193 // WARNING: this code assumes that the return type has already been
194 // typedef-resolved.
195 final Type cReturnType = binding.getCReturnType();
196
197 if (!cReturnType.isVoid()) {
198 // Note we respect const/volatile in the function return type.
199 // However, we cannot have it 'const' for our local variable.
200 // See return type in CMethodBindingEmitter.emitBodyVariableDeclarations(..)!
201 unit.emit("_res = (");
202 unit.emit(cReturnType.getCName(false));
203 unit.emit(") ");
204 }
205 final MethodBinding mBinding = getBinding();
206 if (mBinding.hasContainingType()) {
207 // FIXME: this can and should be handled and unified with the
208 // associated code in the CMethodBindingEmitter
209 throw new IllegalStateException("Cannot call through function pointer because binding has containing type: " + mBinding);
210 }
211
212 // call throught the run-time function pointer
213 unit.emit("(* ptr_");
214 unit.emit(getNativeName());
215 unit.emit(") ");
216 unit.emit("(");
217 emitBodyPassCArguments();
218 unit.emitln(");");
219 }
220 }
221
222 @Override
223 protected String jniMangle(final MethodBinding binding) {
224 final StringBuilder buf = new StringBuilder(super.jniMangle(binding));
225 if (callThroughProcAddress && 0 <= buf.indexOf("__") ) {
226 JavaType.appendJNIDescriptor(buf, Long.TYPE, false); // to account for the additional _addr_ parameter
227 }
228 return buf.toString();
229 }
230}
Emits the C-side component of the Java<->C JNI binding to its CodeUnit, see FunctionEmitter.
final void setTemporaryCVariableDeclarations(final List< String > arg)
Sets up a List of Strings containing declarations for temporary C variables to be assigned to after t...
static final CommentEmitter defaultCommentEmitter
final void setReturnValueCapacityExpression(final MessageFormat expression)
If this function returns a void* encapsulated in a java.nio.Buffer (or compound type wrapper),...
final void setReturnValueLengthExpression(final MessageFormat expression)
If this function returns an array, sets the expression for the length of the returned array.
final void setTemporaryCVariableAssignments(final List< String > arg)
Sets up a List of Strings containing assignments for temporary C variables which are made after the u...
void setCommentEmitter(final CommentEmitter cEmitter)
Set the object that will emit the comment for this function.
JavaConfiguration getConfig()
Describes a java-side representation of a type that is used to represent the same data on both the Ja...
Definition: JavaType.java:54
static StringBuilder appendJNIDescriptor(final StringBuilder res, final Class<?> c, final boolean useTrueType)
Appends the native (JNI) method-name descriptor corresponding to the given Class<?...
Definition: JavaType.java:471
static JavaType createForClass(final Class<?> clazz)
Creates a JavaType corresponding to the given Java type.
Definition: JavaType.java:197
String jniTypeName()
Returns the String corresponding to the JNI type for this type, or NULL if it can't be represented (i...
Definition: JavaType.java:528
Represents the binding of a C function to a Java method.
boolean hasContainingType()
Indicates whether this MethodBinding is for a function pointer contained in a struct,...
Describes a function symbol, which includes the name and type.
FunctionType getType()
Returns the type of this function.
String toString()
Returns a string representation of this type.
final String getCName()
Returns the name of this type.
Definition: Type.java:132
final boolean isVoid()
Indicates whether this is a VoidType.
Definition: Type.java:415
void emitBodyVariablePreCallSetup()
Code to init the variables that were declared in emitBodyVariableDeclarations(), PRIOR TO calling the...
ProcAddressCMethodBindingEmitter(final CMethodBindingEmitter methodToWrap, final boolean callThroughProcAddress, final boolean hasProcAddrTypedef, final String localTypedefCallingConvention, final ProcAddressEmitter emitter)
int appendArguments(final StringBuilder buf)
Returns the number of arguments emitted.
A subclass of JavaEmitter that modifies the normal emission of C and Java code to allow dynamic looku...
String getFunctionPointerTypedefName(final FunctionSymbol sym)
Returns the name of the typedef for a pointer to the function represented by the argument as defined ...