Re: status of nio version
Roger I Martin PhD <[email protected]> Thu, 2 Jun 2005 18:30:38 -0400
| Newsgroups | gmane.comp.windows.devel.jawin |
|---|---|
| Message-ID | <[email protected]> |
Thanks Morten,
A more indept discussion will follow.
Project organization I leave the howto in your hands:-) Let me know
what works for new development being cvs'ed. Branch?
I started an OleControl.cpp so I could work without damaging
GenericStub.cpp but have no plans for pushing it into cvs that way. As
I went I kept using less and less of the original linear stream
transforms and testing. For the valid issues you raise about complex
types, am looking at filling the ByteBuffer with the Variant structure
at the beginning and the rest of it with the data in direct and native
byte order. Then make a pre invoke call to the native to set the
pointers in place. This may be problematic if memory changes but is
there a way to protect from this?
You mention [OUT] parameters in the return and I must display my true
ignorance of the linear byte cpp marshaling:-) I never understood it
and never applied it using all of the return capability:-) Did JNI code
generation instead:-) Originally I wanted to get the stub generator
working in Java with native type info support and xml technology. Then
Josh Passenger built the TypeLib Browser and [whisper] we both wanted
some of the original marshallers to return with enthusiasm. Currently
what I'm trying to do is return everything back thru their place in the
arg list or ByteBuffer array. Maybe I'm changing it too radically.
I can tell you that for the prior marshalling I can only tinker with
fixes but don't understand the native marshaling code. I never saw
anything constructed by the COM side appear on the Java side. Or if a
string changed dimension I never got it. Maybe we didn't finish this
part of new stubbing for the returns?
Quickly, the member id FUNCDEC.memid is used by IDispatch and the
FUNCDESC.oVft is the vtable offset which will figure in coclasses (I did
not have the tlb retrieval supply memid before). In a small test
FUNCDESC.oVft is zero if it is not a virtual function and vice versa for
the FUNCDEC.memid. We can make the GetIDofName
orIDispatch.getIDsofNames functional for those who do not have hard info
on the memid and choose not to use the stub generation? By this it can
be retrieved during run time by the function name as usual.
int id[1];
String names[1];
names[0]=functionName;
getIDsofNames(...names...id
invoke(id[0],....);
every time or they can get all the ones they want during initialization
and use as needed and without repeated calls to getIDsofNames.
More later,
Roger
Morten Andersen wrote:
> Hi Roger,
>
> Impressive thoughts you seem to have put into this. I have added a
> couple of comments, here and there below (I have far from comments or
> ideas on everything, as there are lots I don't know much about)
>
> Roger I Martin PhD wrote:
>
>> 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.
>>
>
> That is of course the safe option. But I fear the risk of bit-root,
> where we suddenly have two different ways to do the same thing, and then
> there will be a risk that one of them doesn't get appropriate attention
> and will degrade over time. I assume I am more to a "hard-cut" switch,
> although I am aware that this may burn some bridges to existing
> developers.
>
> But that is solely up to you.
>
>> 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 details of the IdentityManager is not entirely fresh in my memory.
> But if it is possible to work on the interface only, that is of course
> preferable. But will it be possible without exposing the internal Jawin
> reference counting for GIT-cookie and/or vtable pointer information.
>
> But again this is far away in my memory, so I assume if you have a fresh
> overview of the internal working of IdentityManager, you have considered
> pro and cons.
>
> [SNIP]
>
>
>> 3) Everything I am doing is aimed at speed and seamless bridging.
>
>
> With respect to the speed, a couple of the unittests are actually some
> indicate perfomance tests. That is the classes in test/org/jawin/perf,
> which can be run with "ant test", after this you can inspect the run
> time for these in JUnit-report. I assume you should probably dublicate
> these tests for the new NIO-interface and se what speed gain we can
> expect (we could set up a betting pool in advance :-)).
>
>> 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.
>
>
> That depends a little bit on what direction we want the project to take.
> If I understand you correctly this will disable the option to do
> "type-un-safe" VB-script coding style
> (http://jawinproject.sourceforge.net/jawin.html#callingScript ) and
> force developers to generate and use stubs?
>
> I am not that strong on COM-terms, but is it correctly understood that
> what you suggest is that all stubs should be VTable based, and that we
> won't really use and/or expose the functionality offered by the
> IDispatch interface (or is this just me mixing up terms?).
>
> When discussing if this is direction we want to take, we should probably
> also discuss what support we want for calling old style (non-COM) DLL
> entry points. Is this something we want to keep supporting, or should we
> give up on that part, and refer people to more mature projects for such
> functionality (most of the under-documented marshalling instructions are
> actually for this). Or this something we should direct attention to?
>
> [SNIP]
>
>>
>> 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.
>>
>
> But the "javaOut" byte-array contains both [RETVAL] and [OUT]
> parameters. Will a "random" mix of [RETVAL] and [OUT] parameters still
> be supported with this change?
>
>> 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;
>> }
>
>
> This looks very exciting. So I am understanding it correctly if what you
> want to change the marshalling to is a scheme like:
> "the-java-side-marshall-directly-into-the-native-format"
> which can be pushed directly into the "Invoke" method.
>
> I am not that deep into native Variant types, but is it also possible to
> allocate the Variant-memory for the types with special
> allocation/deallocation methods (I assume this is SafeArray and BSTR and
> perhaps other?), or are this just helper methods MS added to make it
> easier to remember memory-allocation/deallocation for these more complex
> types.
>
> If you want some "weird-type" methods to test on, I think we have some
> for e.g. SafeArrays in SafeArrays in the test class
> test/org/jawin/DispatchTestBase.
>
> Best Regards
> Morten
>