Re: status of nio version

Josh Passenger <[email protected]> Thu, 2 Jun 2005 09:35:17 +1000
Newsgroups gmane.comp.windows.devel.jawin
Message-ID <[email protected]>
All sounds good Roger,

Josh


>There are a number of issues which I would like to know if the changes
>adversely affect anyone.
>
>0) All current marshalling functionality remains available while new
>functionality is added.
>
>1)  Is it a problem for anyone if the IdentityManager uses the IUnknown
>interface to work with the Jawin classes that implement it instead of
>the COMPtr directly?  The COMPtr can still be instantiated by the
>IdentityManager  but requires a cast when returned or used in arguments.
>The reason for the change is to allow other implementations to be
>obtained via the IUnknown interface rather than only extending COMPtr
>which at this time does not permit the object to extend anything else.
>For example a new visual component OLEControl extends
>javax.swing.JWindow and implements IUnknown, IOleControl, IDispatch, etc.
>
>2)  The Jawin Type Browser employs the Saxon XSLT transformer and
>upgrades the code generating stylesheets to XSLT 2.0 and XPath 2.0
>capability.  Very little Type Browser code changes.  We will include the
>saxon jars and license in the downloads and next releases and remove Xalan.
>
>3)  Everything I am doing is aimed at speed and seamless bridging. The
>member id from the function description  will be used instead of passing
>a String with the function name to the new nio native calls and then
>converting to a BSTR and calling the  method to get the member id to
>pass to the IDispatch invoke.  The Jawin Type Browser is updated to
>provide the xml output with the member id.  The vtableoffset will be
>used for virtual function events and callbacks.  Is there any reason
>relying on the member id from the tlb's would be problematic?  I am
>imitating what I see when a OleControl is dropped into a Visual C++
>project.
>
>This eliminates
>        CComBSTR meth;
>        meth.Attach(JNIComUtil::jstobs(env, jmeth));
>            DISPID dwDispID;
>            HRESULT hr = disp.GetIDOfName(meth, &dwDispID);
>            if (SUCCEEDED(hr)) {
>
>from every call.
>
>4) Creating a OleControlStub for all the new marshalling  and leaving
>the GenericStub as is.
>
>5) Am providing an invoke method for every type of return( similar to
>the way JNI is organized).  The stylesheets will pick the right one when
>generating code.
>invokeVoidMethod
>invokeIntMethod
>...
>invokeObjectMethod
>
>These eliminate the need for
>        return MarshalAllocator::allocateByteArray(env,
>javaOut.getMem(), javaOut.getPos());
>and replaces this with the direct application of the return Variant such as
>        return retVar.lVal;
>for integer returning methods.
>
>6) The argument list for every Jawin native invocation call is being
>reduced to jint dwDispID, jobjectArray argArray, jint peer, jint unknown.
>dwDispID = member ID
>argArray = array of java.nio.ByteBuffer's. One for each argument and
>each contains a direct memory access to Variant.
>
>example:
>
>JNIEXPORT jint JNICALL
>Java_org_jawin_marshal_OleControlStub_invokeIntMethod
>  (JNIEnv* env, jobject obj,  jint dwDispID, jobjectArray argArray, jint
>peer, jint unknown)
>
>Notice the instString is gone which eliminates
>
>        JNIComUtil::jstostr(env, instString, str);
>        IStreamOnMemory instructions(str.c_str(), str.length() + 1);
>...
>        Transform tin(env, &br, javaIn, instructions, comIn, NULL);
>...
>        //write retval into stream
>        Transform tret(env, &br, result, instructions, javaOut, NULL);
>        //write out params into stream
>        Transform tout(env, &br, comOut, instructions, javaOut, NULL);
>The direct access to the ByteBuffer variants eliminates
>        IStreamOnMemory javaIn(request, requestSize, env);
>        jint stackSizeWithRet = stackSize + 1;
>
>        // Allocate memory for variants
>        size_t vntsSize = sizeof(VARIANT) * stackSizeWithRet;
>        VARIANT* vnts = (VARIANT*)MarshalAllocator::SafeMalloc(vntsSize,
>NULL); // should we pass the BatchReleaser?
>        for (int i = 0; i < stackSizeWithRet; ++i) {
>            ::VariantInit(vnts + i);
>        }
>        OStreamOnMemory comIn(vnts, vntsSize, true, true);
>...
>        IStreamOnMemory result((byte*)comIn.getMem() +
>stackSize*sizeof(VARIANT), sizeof(VARIANT));
>        IStreamOnMemory comOut((byte*)comIn.getMem(),
>stackSize*sizeof(VARIANT));
>with
>        int arrayLength=env->GetArrayLength(argArray);
>        VARIANTARG* pVar=new VARIANTARG[arrayLength];
>        for(int i=0;i<arrayLength;i++)
>        {
>
>pVar[i]=((VARIANT*)env->GetDirectBufferAddress(env->GetObjectArrayElement(argArray,
>(jint)i)))[0];
>        }
>        VARIANT retVar;
>The marshalling code is simplified to
>JNIEXPORT jint JNICALL
>Java_org_jawin_marshal_OleControlStub_invokeIntMethod
>  (JNIEnv* env, jobject obj,  jint dwDispID, jobjectArray argArray, jint
>peer, jint unknown)
>{
>    long result;
>    se_translator translator;
>    try {
>        int arrayLength=env->GetArrayLength(argArray);
>        VARIANTARG* pVar=new VARIANTARG[arrayLength];
>        for(int i=0;i<arrayLength;i++)
>        {
>
>pVar[i]=((VARIANT*)env->GetDirectBufferAddress(env->GetObjectArrayElement(argArray,
>(jint)i)))[0];
>        }
>        VARIANT retVar;
>        CComPtr<IDispatch> cpUnk;
>        getUnknown(IID_IDispatch, peer, unknown, (IUnknown**) &cpUnk);
>        CComDispatchDriver disp(cpUnk);
>        IOleControl* olectl=NULL;
>        cpUnk->QueryInterface(IID_IOleControl, (void **)&olectl);
>        HRESULT hr;
>                DISPID dispidPut = DISPID_VALUE;//DISPATCH_METHOD;
>                DISPPARAMS dispparams;// = { pVar, NULL,
>(int)stackSize+1, 0};
>                memset(&dispparams, 0, sizeof(dispparams));
>                dispparams.rgvarg=pVar;
>                //dispparams.rgdispidNamedArgs=&dispidPut;
>                dispparams.cArgs=arrayLength;
>                //dispparams.cNamedArgs=1;
>                EXCEPINFO excepInfo;
>                unsigned int argErr;
>                //IDispatch* idisp=(IDispatch*)disp;
>                hr = ((IDispatch*)olectl)->Invoke(dwDispID, IID_NULL,
>LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, &retVar, &excepInfo,
>&argErr);
>                //hr = disp.InvokeN((int)dwDispID, pVar, arrayLength,
>&retVar);
>        olectl->Release();
>             JNI_HR(hr);
>        return retVar.lVal;
>    }
>    HANDLE_WIN32_EXCEPTIONS()
>    HANDLE_JNI_EXCEPTIONS()
>    return 0;
>}
>Note: Still experimenting with which invoke to use.  Having difficulty
>with coclass, GUIDs, CLSIDs, catastrophic failures, etc.:-(
>New functionality needs to be added when the COM constructs and arg or
>changes it's dimension(s).  But notice each arg can be handled
>independently without the need to rearrange a sometimes huge linear byte
>marshalling scheme around; expending and contracting for each changing
>argument.  Now for such any argument it will be possible to natively
>construct a java.nio.ByteBuffer and fill it with an appropriate Variant
>where the type is already known by the Java arg.
>
>7) New put and get calls for the DISPATCH_PROPERTYGET and
>DISPATCH_PROPERTYPUT types of  invokes.  Again similar to JNI there will
>be multiple property invocations such as:
>putInt
>putDouble
>...
>putObject
>...
>getInt
>getDouble
>...
>getObject
>
>Again to eliminate decision making during runtime.  All things that can
>be decided from the type info during the Type Browser and stylesheet
>phase will be used to eliminate runtime decisions and instructions.
>
>
>8)  On the Java side of Jawin a new set of xslt's are being developed to
>create the interface layer.  The interface layer will be larger and
>specific but will no longer call the methods in the Variant class or use
>the org.jawin.io stream classes(NakedByteStream,
>LittleEndianInputStream, LittleEndianOutputStream)  A typical interface
>method will look like:
>    public int IntegerTest(int index) throws COMException
>    {
>      java.nio.ByteBuffer[] bba=new java.nio.ByteBuffer[1];
>      java.nio.ByteBuffer bb=java.nio.ByteBuffer.allocateDirect(16);
>      bb.order(java.nio.ByteOrder.nativeOrder());
>
>bba[0]=bb.putShort((short)VarTypes.VT_I4).putShort((short)0).putShort((short)0).putShort((short)0).putInt(index);
>      return invokeIntMethod((int)0x01, bba);
>
>    }
>
>
>9)  The JAWT functionality allows a visible Ole Control window to be
>painted onto the surface of a java.awt.Canvas in a javax.swing.JWindow.
>createControl and paint methods are being added to implement visible
>painting.
>
>10) still testing how to get a generic C++ callback function to employ
>for every virtual function in the vtable.  When we have it, from it we
>can call the coclasses Java interface methods where the user can write
>their Java implementation.  Any howto information on this part would be
>greatly appreciated.
>
>Any thoughts, ideas, foreseeable troubles with the refactoring and
>applying nio are appreciated.
>
>-Roger