BufferNativeInvoker.java

  1. package org.jruby.ext.ffi.jffi;

  2. import com.kenai.jffi.HeapInvocationBuffer;
  3. import org.jruby.RubyModule;
  4. import org.jruby.runtime.Arity;
  5. import org.jruby.runtime.ThreadContext;
  6. import org.jruby.runtime.builtin.IRubyObject;

  7. /**
  8.  * Invokes a native function using InvocationBuffer methods.
  9.  */
  10. final class BufferNativeInvoker extends NativeInvoker {
  11.     private final com.kenai.jffi.Function function;
  12.     private final FunctionInvoker functionInvoker;
  13.     private final ParameterMarshaller[] parameterMarshallers;
  14.     private final boolean needsInvocationSession;
  15.     private final int postInvokeCount;
  16.     private final int referenceCount;
  17.     private final HeapInvocationBuffer dummyBuffer;
  18.    
  19.    
  20.     BufferNativeInvoker(RubyModule implementationClass, com.kenai.jffi.Function function, Signature signature,
  21.             FunctionInvoker functionInvoker,
  22.             ParameterMarshaller[] parameterMarshallers) {
  23.         super(implementationClass, function, signature);
  24.         this.function = function;
  25.         this.functionInvoker = functionInvoker;
  26.         this.parameterMarshallers = parameterMarshallers.clone();
  27.        
  28.         int piCount = 0;
  29.         int refCount = 0;
  30.         for (ParameterMarshaller m : parameterMarshallers) {
  31.             if (m.requiresPostInvoke()) {
  32.                 ++piCount;
  33.             }

  34.             if (m.requiresReference()) {
  35.                 ++refCount;
  36.             }
  37.         }
  38.         this.postInvokeCount = piCount;
  39.         this.referenceCount = refCount;
  40.         this.needsInvocationSession = piCount > 0 || refCount > 0;
  41.         this.dummyBuffer = new HeapInvocationBuffer(function);
  42.     }
  43.    
  44.    
  45.     public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule klazz, String name) {
  46.         return functionInvoker.invoke(context, function, dummyBuffer);
  47.     }
  48.    
  49.     public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule klazz, String name, IRubyObject arg1) {
  50.         HeapInvocationBuffer buffer = new HeapInvocationBuffer(function);
  51.        
  52.         if (needsInvocationSession) {
  53.             Invocation invocation = new Invocation(context, postInvokeCount, referenceCount);
  54.             try {
  55.                 parameterMarshallers[0].marshal(invocation, buffer, arg1);
  56.                
  57.                 return functionInvoker.invoke(context, function, buffer);
  58.            
  59.             } finally {
  60.                 invocation.finish();
  61.             }
  62.        
  63.         } else {
  64.             parameterMarshallers[0].marshal(context, buffer, arg1);
  65.            
  66.             return functionInvoker.invoke(context, function, buffer);
  67.         }
  68.     }
  69.    
  70.     public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule klazz, String name,
  71.                             IRubyObject arg1, IRubyObject arg2) {
  72.         HeapInvocationBuffer buffer = new HeapInvocationBuffer(function);
  73.         if (needsInvocationSession) {
  74.             Invocation invocation = new Invocation(context, postInvokeCount, referenceCount);
  75.             try {
  76.                 parameterMarshallers[0].marshal(invocation, buffer, arg1);
  77.                 parameterMarshallers[1].marshal(invocation, buffer, arg2);
  78.            
  79.                 return functionInvoker.invoke(context, function, buffer);
  80.            
  81.             } finally {
  82.                 invocation.finish();
  83.             }
  84.        
  85.         } else {
  86.             parameterMarshallers[0].marshal(context, buffer, arg1);
  87.             parameterMarshallers[1].marshal(context, buffer, arg2);
  88.            
  89.             return functionInvoker.invoke(context, function, buffer);
  90.         }
  91.     }
  92.    
  93.     public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule klazz, String name,
  94.                             IRubyObject arg1, IRubyObject arg2, IRubyObject arg3) {
  95.         HeapInvocationBuffer buffer = new HeapInvocationBuffer(function);
  96.         if (needsInvocationSession) {
  97.             Invocation invocation = new Invocation(context, postInvokeCount, referenceCount);
  98.             try {
  99.                 parameterMarshallers[0].marshal(invocation, buffer, arg1);
  100.                 parameterMarshallers[1].marshal(invocation, buffer, arg2);
  101.                 parameterMarshallers[2].marshal(invocation, buffer, arg3);
  102.                
  103.                 return functionInvoker.invoke(context, function, buffer);
  104.             } finally {
  105.                 invocation.finish();
  106.             }
  107.        
  108.         } else {
  109.             parameterMarshallers[0].marshal(context, buffer, arg1);
  110.             parameterMarshallers[1].marshal(context, buffer, arg2);
  111.             parameterMarshallers[2].marshal(context, buffer, arg3);
  112.        
  113.             return functionInvoker.invoke(context, function, buffer);
  114.         }
  115.     }


  116.     public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule klazz, String name, IRubyObject[] args) {
  117.        
  118.         HeapInvocationBuffer buffer = new HeapInvocationBuffer(function);

  119.         if (needsInvocationSession) {
  120.             Invocation invocation = new Invocation(context, postInvokeCount, referenceCount);
  121.             try {
  122.                 for (int i = 0; i < args.length; ++i) {
  123.                     parameterMarshallers[i].marshal(invocation, buffer, args[i]);
  124.                 }
  125.                 return functionInvoker.invoke(context, function, buffer);
  126.            
  127.             } finally {
  128.                 invocation.finish();
  129.             }
  130.        
  131.         } else {
  132.             for (int i = 0; i < args.length; ++i) {
  133.                 parameterMarshallers[i].marshal(context, buffer, args[i]);
  134.             }

  135.             return functionInvoker.invoke(context, function, buffer);
  136.         }
  137.     }
  138.    
  139. }