001/*
002 * BridJ - Dynamic and blazing-fast native interop for Java.
003 * http://bridj.googlecode.com/
004 *
005 * Copyright (c) 2010-2013, Olivier Chafik (http://ochafik.com/)
006 * All rights reserved.
007 *
008 * Redistribution and use in source and binary forms, with or without
009 * modification, are permitted provided that the following conditions are met:
010 * 
011 *     * Redistributions of source code must retain the above copyright
012 *       notice, this list of conditions and the following disclaimer.
013 *     * Redistributions in binary form must reproduce the above copyright
014 *       notice, this list of conditions and the following disclaimer in the
015 *       documentation and/or other materials provided with the distribution.
016 *     * Neither the name of Olivier Chafik nor the
017 *       names of its contributors may be used to endorse or promote products
018 *       derived from this software without specific prior written permission.
019 * 
020 * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY
021 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
023 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
024 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
027 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
030 */
031package org.bridj;
032
033import java.lang.annotation.Annotation;
034import static org.bridj.NativeConstants.*;
035import static org.bridj.dyncall.DyncallLibrary.*;
036import org.bridj.ann.Constructor;
037//import org.bridj.cpp.CPPObject;
038
039import java.lang.reflect.*;
040import java.util.ArrayList;
041import java.util.Arrays;
042import java.util.List;
043import java.util.NoSuchElementException;
044import org.bridj.ann.Convention;
045import org.bridj.ann.SetsLastError;
046import org.bridj.ann.DisableDirect;
047import org.bridj.ann.Ptr;
048import org.bridj.ann.Virtual;
049import org.bridj.util.Utils;
050import static org.bridj.util.AnnotationUtils.*;
051
052/**
053 * Internal class that encapsulate all the knowledge about a native method call
054 * : signatures (ASM, dyncall and Java), calling convention, context...
055 *
056 * @author Olivier
057 */
058public class MethodCallInfo {
059
060    /*public static class GenericMethodInfo {
061     Type returnType, paramsTypes[];
062     }
063     GenericMethodInfo genericInfo = new GenericMethodInfo();*/
064    List<CallIO> callIOs;
065    private Class<?> declaringClass;
066    long nativeClass;
067    int returnValueType, paramsValueTypes[];
068    Method method;//, definition;
069    String methodName, symbolName;
070    private long forwardedPointer;
071    String dcSignature;
072    String javaSignature;
073    String asmSignature;
074    Object javaCallback;
075    boolean isGenericCallback;
076    boolean isObjCBlock;
077    int virtualIndex = -1;
078    int virtualTableOffset = 0;
079    private int dcCallingConvention = DC_CALL_C_DEFAULT;
080    boolean isVarArgs;
081    boolean isStatic;
082    boolean isCPlusPlus;
083    boolean direct;
084    boolean startsWithThis;
085    boolean bNeedsThisPointer;
086    boolean throwsLastError;
087    boolean setsLastError;
088
089    public MethodCallInfo(Method method) {
090        this(method, method);
091    }
092
093    static boolean derivesFrom(Class<?> c, String className) {
094        while (c != null) {
095            if (c.getName().equals(className)) {
096                return true;
097            }
098            c = c.getSuperclass();
099        }
100        return false;
101    }
102
103    public MethodCallInfo(Type genericReturnType, Type[] parameterTypes, boolean prependJNIPointers) {
104        this(genericReturnType, new Annotation[0], parameterTypes, new Annotation[parameterTypes.length][], prependJNIPointers);
105    }
106
107    public MethodCallInfo(Type genericReturnType, Annotation[] returnAnnotations, Type[] parameterTypes, Annotation[][] paramsAnnotations, boolean prependJNIPointers) {
108        init(null, Utils.getClass(genericReturnType), genericReturnType, returnAnnotations, Utils.getClasses(parameterTypes), parameterTypes, paramsAnnotations, prependJNIPointers, false, true);
109    }
110
111    public MethodCallInfo(Method method, Method definition) {
112        this.setMethod(method);
113        //this.setDefinition(definition);
114        this.setDeclaringClass(method.getDeclaringClass());
115        symbolName = methodName;
116
117        int modifiers = method.getModifiers();
118        isStatic = Modifier.isStatic(modifiers);
119        isVarArgs = method.isVarArgs();
120        boolean isNative = Modifier.isNative(modifiers);
121        boolean isVirtual = isAnnotationPresent(Virtual.class, definition);
122        boolean isDirectModeAllowed =
123                getInheritableAnnotation(DisableDirect.class, definition) == null
124                && BridJ.isDirectModeEnabled();
125
126        isCPlusPlus = !isStatic && derivesFrom(method.getDeclaringClass(), "org.bridj.cpp.CPPObject");
127        isObjCBlock = !isStatic && derivesFrom(method.getDeclaringClass(), "org.bridj.objc.ObjCBlock");
128
129        init(
130                method,
131                method.getReturnType(), method.getGenericReturnType(), method.getAnnotations(),
132                method.getParameterTypes(), method.getGenericParameterTypes(), method.getParameterAnnotations(),
133                isNative,
134                isVirtual,
135                isDirectModeAllowed);
136
137        Convention cc = getInheritableAnnotation(Convention.class, definition);
138        if (cc != null) {
139            setCallingConvention(cc.value());
140        }
141        List<Class<?>> exceptionTypes = Arrays.asList(definition.getExceptionTypes());
142        if (!exceptionTypes.isEmpty()) {
143            this.direct = false; // there is no crash / exception protection for direct raw calls
144            if (exceptionTypes.contains(LastError.class)) {
145                this.throwsLastError = true;
146                this.setsLastError = true;
147            }
148        }
149        if (getInheritableAnnotation(SetsLastError.class, definition) != null) {
150            this.direct = false; // there is no crash / exception protection for direct raw calls
151            this.setsLastError = true;
152        }
153
154    }
155
156    protected void init(AnnotatedElement annotatedElement, Class returnType, Type genericReturnType, Annotation[] returnAnnotations, Class[] parameterTypes, Type[] genericParameterTypes, Annotation[][] paramsAnnotations, boolean prependJNIPointers, boolean isVirtual, boolean isDirectModeAllowed) {
157        assert returnType != null;
158        assert genericReturnType != null;
159        assert parameterTypes != null;
160        assert genericParameterTypes != null;
161        assert returnAnnotations != null;
162        assert parameterTypes.length == genericParameterTypes.length;
163        assert paramsAnnotations.length == genericParameterTypes.length;
164
165        int nParams = genericParameterTypes.length;
166        paramsValueTypes = new int[nParams];
167
168        direct = isDirectModeAllowed; // TODO on native side : test number of parameters (on 64 bits win : must be <= 4)
169
170        StringBuilder javaSig = new StringBuilder(64),
171                asmSig = new StringBuilder(64),
172                dcSig = new StringBuilder(16);
173        javaSig.append('(');
174        asmSig.append('(');
175        if (prependJNIPointers)//!isCPlusPlus)
176        {
177            dcSig.append(DC_SIGCHAR_POINTER).append(DC_SIGCHAR_POINTER); // JNIEnv*, jobject: always present in native-bound functions
178        }
179        if (BridJ.debug) {
180            BridJ.info("Analyzing " + (declaringClass == null ? "anonymous method" : declaringClass.getName() + "." + methodName));
181        }
182
183        if (isObjCBlock) {
184            appendToSignature(0, ValueType.ePointerValue, Pointer.class, Pointer.class, null, dcSig, null);
185        }
186
187        for (int iParam = 0; iParam < nParams; iParam++) {
188//            Options paramOptions = paramsOptions[iParam] = new Options();
189            Type genericParameterType = genericParameterTypes[iParam];
190            Class<?> parameterType = parameterTypes[iParam];
191
192            ValueType paramValueType = getValueType(iParam, nParams, parameterType, genericParameterType, null, paramsAnnotations[iParam]);
193            if (BridJ.veryVerbose) {
194                BridJ.info("\tparam " + paramValueType);
195            }
196            paramsValueTypes[iParam] = paramValueType.ordinal();
197
198            appendToSignature(iParam, paramValueType, parameterType, genericParameterType, javaSig, dcSig, asmSig);
199        }
200        javaSig.append(')');
201        asmSig.append(')');
202        dcSig.append(')');
203
204        ValueType retType = getValueType(-1, nParams, returnType, genericReturnType, annotatedElement, returnAnnotations);
205        if (BridJ.veryVerbose) {
206            BridJ.info("\treturns " + retType);
207        }
208        appendToSignature(-1, retType, returnType, genericReturnType, javaSig, dcSig, asmSig);
209        returnValueType = retType.ordinal();
210
211        javaSignature = javaSig.toString();
212        asmSignature = asmSig.toString();
213        dcSignature = dcSig.toString();
214
215        isCPlusPlus = isCPlusPlus || isVirtual;
216
217        if (isCPlusPlus && !isStatic) {
218            if (!startsWithThis) {
219                direct = false;
220            }
221            bNeedsThisPointer = true;
222            if (Platform.isWindows()) {
223                if (!Platform.is64Bits()) {
224                    setDcCallingConvention(DC_CALL_C_X86_WIN32_THIS_MS);
225                }
226            } else {
227                //if (!Platform.is64Bits())
228                //      setDcCallingConvention(DC_CALL_C_X86_WIN32_THIS_GNU);
229            }
230        }
231
232        if (nParams > Platform.getMaxDirectMappingArgCount()) {
233            this.direct = false;
234        }
235
236        if (BridJ.veryVerbose) {
237            BridJ.info("\t-> direct " + direct);
238            BridJ.info("\t-> javaSignature " + javaSignature);
239            BridJ.info("\t-> callIOs " + callIOs);
240            BridJ.info("\t-> asmSignature " + asmSignature);
241            BridJ.info("\t-> dcSignature " + dcSignature);
242        }
243
244        if (BridJ.veryVerbose) {
245            BridJ.info((direct ? "[mappable as direct] " : "[not mappable as direct] ") + method);
246        }
247    }
248    boolean hasCC;
249
250    public boolean hasCallingConvention() {
251        return hasCC;
252    }
253
254    public void setCallingConvention(Convention.Style style) {
255        if (style == null) {
256            return;
257        }
258
259        if (!Platform.isWindows() || Platform.is64Bits()) {
260            return;
261        }
262
263        switch (style) {
264            case FastCall:
265                this.direct = false;
266                setDcCallingConvention(Platform.isWindows() ? DC_CALL_C_X86_WIN32_FAST_MS : DC_CALL_C_DEFAULT); // TODO allow GCC-compiled C++ libs on windows
267                break;
268            case Pascal:
269            case StdCall:
270                this.direct = false;
271                setDcCallingConvention(DC_CALL_C_X86_WIN32_STD);
272                break;
273            case ThisCall:
274                this.direct = false;
275                setDcCallingConvention(Platform.isWindows() ? DC_CALL_C_X86_WIN32_THIS_MS : DC_CALL_C_DEFAULT);
276        }
277        if (BridJ.veryVerbose) {
278            BridJ.info("Setting CC " + style + " (-> " + dcCallingConvention + ") for " + methodName);
279        }
280
281    }
282
283    void addCallIO(CallIO handler) {
284        if (callIOs == null) {
285            callIOs = new ArrayList<CallIO>();
286        }
287        assert handler != null;
288        callIOs.add(handler);
289    }
290
291    public CallIO[] getCallIOs() {
292        if (callIOs == null) {
293            return new CallIO[0];
294        }
295        return callIOs.toArray(new CallIO[callIOs.size()]);
296    }
297
298    public void prependCallbackCC() {
299        char cc = getDcCallbackConvention(getDcCallingConvention());
300        if (cc == 0) {
301            return;
302        }
303
304        dcSignature = String.valueOf(DC_SIGCHAR_CC_PREFIX) + String.valueOf(cc) + dcSignature;
305    }
306
307    public String getDcSignature() {
308        return dcSignature;
309    }
310
311    public String getJavaSignature() {
312        return javaSignature;
313    }
314
315    public String getASMSignature() {
316        return asmSignature;
317    }
318
319    boolean getBoolAnnotation(Class<? extends Annotation> ac, AnnotatedElement element, Annotation... directAnnotations) {
320        Annotation ann = getAnnotation(ac, element, directAnnotations);
321        return ann != null;
322    }
323
324    public ValueType getValueType(int iParam, int nParams, Class<?> c, Type t, AnnotatedElement element, Annotation... directAnnotations) {
325        boolean isPtr = isAnnotationPresent(Ptr.class, element, directAnnotations);
326        boolean isCLong = isAnnotationPresent(org.bridj.ann.CLong.class, element, directAnnotations);
327        Constructor cons = getAnnotation(Constructor.class, element, directAnnotations);
328
329        if (isPtr || cons != null || isCLong) {
330            if (!(c == Long.class || c == Long.TYPE)) {
331                throw new RuntimeException("Annotation should only be used on a long parameter, not on a " + c.getName());
332            }
333
334            if (isPtr) {
335                if (!Platform.is64Bits()) {
336                    direct = false;
337                }
338            } else if (isCLong) {
339                if (Platform.CLONG_SIZE != 8) {
340                    direct = false;
341                }
342            } else if (cons != null) {
343                isCPlusPlus = true;
344                startsWithThis = true;
345                if (iParam != 0) {
346                    throw new RuntimeException("Annotation " + Constructor.class.getName() + " cannot have more than one (long) argument");
347                }
348            }
349            return isCLong ? ValueType.eCLongValue : ValueType.eSizeTValue;
350        }
351        if (c == null || c.equals(Void.TYPE)) {
352            return ValueType.eVoidValue;
353        }
354        if (c == Integer.class || c == Integer.TYPE) {
355            return ValueType.eIntValue;
356        }
357        if (c == Long.class || c == Long.TYPE) {
358            return !isPtr || Platform.is64Bits() ? ValueType.eLongValue : ValueType.eIntValue;
359        }
360        if (c == Short.class || c == Short.TYPE) {
361            return ValueType.eShortValue;
362        }
363        if (c == Byte.class || c == Byte.TYPE) {
364            return ValueType.eByteValue;
365        }
366        if (c == Boolean.class || c == Boolean.TYPE) {
367            return ValueType.eBooleanValue;
368        }
369        if (c == Float.class || c == Float.TYPE) {
370            usesFloats();
371            return ValueType.eFloatValue;
372        }
373        if (c == char.class || c == Character.TYPE) {
374            if (Platform.WCHAR_T_SIZE != 2) {
375                direct = false;
376            }
377            return ValueType.eWCharValue;
378        }
379        if (c == Double.class || c == Double.TYPE) {
380            usesFloats();
381            return ValueType.eDoubleValue;
382        }
383        if (c == CLong.class) {
384            direct = false;
385            return ValueType.eCLongObjectValue;
386        }
387        if (c == SizeT.class) {
388            direct = false;
389            return ValueType.eSizeTObjectValue;
390        }
391        if (c == TimeT.class) {
392            direct = false;
393            return ValueType.eTimeTObjectValue;
394        }
395        if (Pointer.class.isAssignableFrom(c)) {
396            direct = false;
397            CallIO cio = CallIO.Utils.createPointerCallIO(c, t);
398            if (BridJ.veryVerbose) {
399                BridJ.info("CallIO : " + cio);
400            }
401            addCallIO(cio);
402            return ValueType.ePointerValue;
403        }
404        if (c.isArray() && iParam == nParams - 1) {
405            direct = false;
406            return ValueType.eEllipsis;
407        }
408        if (ValuedEnum.class.isAssignableFrom(c)) {
409            direct = false;
410            CallIO cio = CallIO.Utils.createValuedEnumCallIO((Class) Utils.getClass(Utils.getUniqueParameterizedTypeParameter(t)));
411            if (BridJ.veryVerbose) {
412                BridJ.info("CallIO : " + cio);
413            }
414            addCallIO(cio);
415
416            return ValueType.eIntFlagSet;
417        }
418        if (NativeObject.class.isAssignableFrom(c)) {
419            Pointer<DCstruct> pStruct = null;
420            if (StructObject.class.isAssignableFrom(c)) {
421                StructIO io = StructIO.getInstance(c, t);
422                try {
423                    pStruct = DyncallStructs.buildDCstruct(io.desc);
424                } catch (Throwable th) {
425                    BridJ.error("Unable to create low-level struct metadata for " + Utils.toString(t) + " : won't be able to use it as a by-value function argument.", th);
426                }
427            }
428            addCallIO(new CallIO.NativeObjectHandler((Class<? extends NativeObject>) c, t, pStruct));
429            direct = false;
430            return ValueType.eNativeObjectValue;
431        }
432
433        throw new NoSuchElementException("No " + ValueType.class.getSimpleName() + " for class " + c.getName());
434    }
435
436    void usesFloats() {
437        /*
438         if (direct && Platform.isMacOSX()) {
439         direct = false;
440         assert BridJ.warning("[unstable direct] FIXME Disable direct call due to float/double usage in " + method);
441         }
442         */
443    }
444
445    public void appendToSignature(int iParam, ValueType type, Class<?> parameterType, Type genericParameterType, StringBuilder javaSig, StringBuilder dcSig, StringBuilder asmSig) {
446        char dcChar;
447        String javaChar, asmChar = null;
448        switch (type) {
449            case eVoidValue:
450                dcChar = DC_SIGCHAR_VOID;
451                javaChar = "V";
452                break;
453            case eIntValue:
454                dcChar = DC_SIGCHAR_INT;
455                javaChar = "I";
456                break;
457            case eLongValue:
458                dcChar = DC_SIGCHAR_LONGLONG;
459                javaChar = "J";
460                break;
461            case eCLongValue:
462                javaChar = "J";
463                                dcChar = DC_SIGCHAR_LONG;
464                if (Platform.CLONG_SIZE != 8) {
465                    direct = false;
466                }
467                break;
468            case eSizeTValue:
469                javaChar = "J";
470                if (Platform.SIZE_T_SIZE == 8) {
471                    dcChar = DC_SIGCHAR_LONGLONG;
472                } else {
473                    dcChar = DC_SIGCHAR_INT;
474                    direct = false;
475                }
476                break;
477            case eShortValue:
478                dcChar = DC_SIGCHAR_SHORT;
479                javaChar = "S";
480                break;
481            case eDoubleValue:
482                dcChar = DC_SIGCHAR_DOUBLE;
483                javaChar = "D";
484                break;
485            case eFloatValue:
486                dcChar = DC_SIGCHAR_FLOAT;
487                javaChar = "F";
488                break;
489            case eByteValue:
490                dcChar = DC_SIGCHAR_CHAR;
491                javaChar = "B";
492                break;
493            case eBooleanValue:
494                dcChar = DC_SIGCHAR_BOOL;
495                javaChar = "Z";
496                break;
497            case eWCharValue:
498                switch (Platform.WCHAR_T_SIZE) {
499                    case 1:
500                        dcChar = DC_SIGCHAR_CHAR;
501                        direct = false;
502                        break;
503                    case 2:
504                        dcChar = DC_SIGCHAR_SHORT;
505                        break;
506                    case 4:
507                        dcChar = DC_SIGCHAR_INT;
508                        direct = false;
509                        break;
510                    default:
511                        throw new RuntimeException("Unhandled sizeof(wchar_t) in GetJavaTypeSignature: " + Platform.WCHAR_T_SIZE);
512                }
513                javaChar = "C";
514                break;
515            case eIntFlagSet:
516                dcChar = DC_SIGCHAR_INT;
517                javaChar = "L" + parameterType.getName().replace('.', '/') + ";";//"Lorg/bridj/ValuedEnum;";
518                direct = false;
519                break;
520            case eCLongObjectValue:
521                dcChar = DC_SIGCHAR_POINTER;
522                javaChar = "Lorg/bridj/CLong;";
523                direct = false;
524                break;
525            case eSizeTObjectValue:
526                dcChar = DC_SIGCHAR_POINTER;
527                javaChar = "Lorg/bridj/SizeT;";
528                direct = false;
529                break;
530            case eTimeTObjectValue:
531                dcChar = DC_SIGCHAR_POINTER;
532                javaChar = "Lorg/bridj/TimeT;";
533                direct = false;
534                break;
535            case ePointerValue:
536                dcChar = DC_SIGCHAR_POINTER;
537                javaChar = "L" + parameterType.getName().replace('.', '/') + ";";
538//                javaChar = "Lorg/bridj/Pointer;";
539                direct = false;
540                break;
541            case eNativeObjectValue:
542                dcChar = DC_SIGCHAR_STRUCT; // TODO : unroll struct signature ?
543                javaChar = "L" + parameterType.getName().replace('.', '/') + ";";
544                direct = false;
545//              if (parameterType.equals(declaringClass)) {
546//                    // special case of self-returning pointers
547//                    dcChar = DC_SIGCHAR_POINTER;
548                break;
549            case eEllipsis:
550                javaChar = "[Ljava/lang/Object;";
551                dcChar = '?';
552                break;
553            default:
554                direct = false;
555                throw new RuntimeException("Unhandled " + ValueType.class.getSimpleName() + ": " + type);
556        }
557        if (genericParameterType instanceof ParameterizedType && iParam < 0) {
558            ParameterizedType pt = (ParameterizedType) genericParameterType;
559            // TODO handle all cases !!!
560            Type[] ts = pt.getActualTypeArguments();
561            if (ts != null && ts.length == 1) {
562                Type t = ts[0];
563                if (t instanceof ParameterizedType) {
564                    t = ((ParameterizedType) t).getRawType();
565                }
566                if (t instanceof Class) {
567                    Class c = (Class) t;
568                    if (javaChar.endsWith(";")) {
569                        asmChar = javaChar.substring(0, javaChar.length() - 1) + "<*L" + c.getName().replace('.', '/') + ";>";
570                        //asmChar += ";";
571                    }
572                }
573            }
574        }
575        if (javaSig != null) {
576            javaSig.append(javaChar);
577        }
578        if (asmChar == null) {
579            asmChar = javaChar;
580        }
581        if (asmSig != null) {
582            asmSig.append(asmChar);
583        }
584        if (dcSig != null) {
585            dcSig.append(dcChar);
586        }
587    }
588    /*
589     public void setDefinition(Method definition) {
590     this.definition = definition;
591     }
592
593     public Method getDefinition() {
594     return definition;
595     }
596     */
597
598    public void setMethod(Method method) {
599        this.method = method;
600        if (method != null) {
601            this.methodName = method.getName();
602        }
603        if (declaringClass == null) {
604            setDeclaringClass(method.getDeclaringClass());
605        }
606
607    }
608
609    public void setJavaSignature(String javaSignature) {
610        this.javaSignature = javaSignature;
611    }
612
613    public Method getMethod() {
614        return method;
615    }
616
617    public void setDeclaringClass(Class<?> declaringClass) {
618        this.declaringClass = declaringClass;
619    }
620
621    public Class<?> getDeclaringClass() {
622        return declaringClass;
623    }
624
625    public void setForwardedPointer(long forwardedPointer) {
626        this.forwardedPointer = forwardedPointer;
627    }
628
629    public long getForwardedPointer() {
630        return forwardedPointer;
631    }
632
633    /**
634     * Used for C++ virtual indexes and for struct fields ids
635     *
636     * @param virtualIndex
637     */
638    public void setVirtualIndex(int virtualIndex) {
639        //new RuntimeException("Setting virtualIndex of " + getMethod().getName() + " = " + virtualIndex).printStackTrace();
640        this.virtualIndex = virtualIndex;
641
642        if (BridJ.veryVerbose) {
643            BridJ.info("\t-> virtualIndex " + virtualIndex);
644        }
645    }
646
647    public int getVirtualIndex() {
648        return virtualIndex;
649    }
650
651    public String getSymbolName() {
652        return symbolName;
653    }
654
655    public void setSymbolName(String symbolName) {
656        this.symbolName = symbolName;
657    }
658
659    static char getDcCallbackConvention(int dcCallingConvention) {
660        switch (dcCallingConvention) {
661            case DC_CALL_C_X86_WIN32_STD:
662                return DC_SIGCHAR_CC_STDCALL;
663            case DC_CALL_C_X86_WIN32_FAST_MS:
664                return DC_SIGCHAR_CC_FASTCALL_MS;
665            case DC_CALL_C_X86_WIN32_FAST_GNU:
666                return DC_SIGCHAR_CC_FASTCALL_GNU;
667            case DC_CALL_C_X86_WIN32_THIS_MS:
668                return DC_SIGCHAR_CC_THISCALL_MS;
669            default:
670                return 0;
671        }
672    }
673
674    public void setDcCallingConvention(int dcCallingConvention) {
675        hasCC = true;
676        this.dcCallingConvention = dcCallingConvention;
677    }
678
679    public int getDcCallingConvention() {
680        return dcCallingConvention;
681    }
682
683    public Object getJavaCallback() {
684        return javaCallback;
685    }
686
687    public void setJavaCallback(Object javaCallback) {
688        this.javaCallback = javaCallback;
689    }
690
691    public void setGenericCallback(boolean genericCallback) {
692        this.isGenericCallback = genericCallback;
693    }
694
695    public boolean isGenericCallback() {
696        return isGenericCallback;
697    }
698
699    public void setNativeClass(long nativeClass) {
700        this.nativeClass = nativeClass;
701    }
702}