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 org.bridj.CRuntime.MethodCallInfoBuilder;
034import org.bridj.ann.Convention;
035import java.lang.reflect.Constructor;
036import java.lang.reflect.Method;
037
038import static org.bridj.Pointer.*;
039
040/**
041 * Factory that is able to create dynamic functions bindings with a given
042 * signature
043 */
044public class DynamicFunctionFactory {
045
046    final Constructor<? extends DynamicFunction> constructor;
047    final Method method;
048    final long callbackHandle;
049
050    DynamicFunctionFactory(Class<? extends DynamicFunction> callbackClass, Method method, /*Convention.Style style,*/ MethodCallInfoBuilder methodCallInfoBuilder) {
051        try {
052            this.constructor = callbackClass.getConstructor();
053            this.method = method;
054
055            MethodCallInfo mci = methodCallInfoBuilder.apply(method);
056            callbackHandle = JNI.bindJavaToCCallbacks(mci);
057        } catch (Throwable th) {
058            th.printStackTrace();
059            throw new RuntimeException("Failed to instantiate callback" + " : " + th, th);
060        }
061    }
062
063    @Override
064    protected void finalize() throws Throwable {
065        if (BridJ.debugNeverFree) {
066            return;
067        }
068
069        JNI.freeJavaToCCallbacks(callbackHandle, 1);
070    }
071
072    public DynamicFunction newInstance(Pointer<?> functionPointer) {
073        if (functionPointer == null) {
074            return null;
075        }
076
077        try {
078            DynamicFunction dcb = constructor.newInstance();
079            dcb.peer = (Pointer) functionPointer;
080            dcb.method = method;
081            dcb.factory = this;
082
083            return dcb;
084        } catch (Throwable th) {
085            th.printStackTrace();
086            throw new RuntimeException("Failed to instantiate callback" + " : " + th, th);
087        }
088    }
089
090    @Override
091    public String toString() {
092        return getClass().getSimpleName() + "(" + method + ")";
093    }
094}