Re: status of nio version
"Christophe Warland (FRSGlobal)" <[email protected]> Thu, 2 Jun 2005 12:28:25 -0400
| Newsgroups | gmane.comp.windows.devel.jawin |
|---|---|
| Message-ID | <[email protected]> |
Sounds nice, thank you for be willing to do all that work! One extra refactoring feature I'd like to ask for is to make it so that all methods in COMPtr and DispatchPtr are declared in a separate interface that would be implemented by instances of those classes. It would allow me to develop some nifty Java Dynamic Proxies on top of. Today, I have to do some advance java.reflect tricks to do what regular proxies could do out of the box with interfaces. Thanks! -- Christophe -----Original Message----- From: Roger I Martin PhD [mailto:[email protected]] Sent: Wednesday, June 01, 2005 4:01 PM To: [email protected] Subject: status of nio version 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(ar gArray, (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(ar gArray, (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