Search code examples
c#javaremotingcorbaiiop

How to specify a CodeSet for WChar string from a CORBA client


This question is related to another question with which I have been struggling: How to access CORBA interface without IDL or late-bound invoke remoting methods

I'm really stumped on how to get past this error about the CodeSet not being specified. I have been tracing into the IIOP code trying to figure out how the CodeSet can be specified, and it looks like it could be specified with a tagged component associated with the profile. Being unfamiliar with CORBA, I don't know what a tagged component is or what a profile is or how to control them, but I suspect that it may be influenced by creating a portable object interceptor, at which point I could add a tagged CodeSet component to the profile, if that means anything. I'm just going by what I can learn from the IIOP.NET code and Google.

Could someone please help me understand and hopefully control this? If the server is a black box and I need to write a client to call a method that outputs a string, how do I tell IIOP.NET what WChar CodeSet to use so it doesn't give me an error about it being unspecified. I tried OverrideDefaultCharSets from the client, but that didn't seem to have any effect. The IIOP sample code for that function shows it being used on the server side.


Solution

  • This was a real pain to work out, but I got it:

    class MyOrbInitializer : omg.org.PortableInterceptor.ORBInitializer
    {
        public void post_init(omg.org.PortableInterceptor.ORBInitInfo info)
        {
            // Nothing to do
        }
    
        public void pre_init(omg.org.PortableInterceptor.ORBInitInfo info)
        {
            omg.org.IOP.Codec codec = info.codec_factory.create_codec(
                new omg.org.IOP.Encoding(omg.org.IOP.ENCODING_CDR_ENCAPS.ConstVal, 1, 2));
            Program.m_codec = codec;
        }
    }
    
    
    class Program
    {
        public static omg.org.IOP.Codec m_codec;
    
        static void Main(string[] args)
        {
            IOrbServices orb = OrbServices.GetSingleton();
            orb.OverrideDefaultCharSets(CharSet.UTF8, WCharSet.UTF16);
            orb.RegisterPortableInterceptorInitalizer(new MyOrbInitializer());
            orb.CompleteInterceptorRegistration();
    ...
            MarshalByRefObject objRef = context.resolve(names);
            string origObjData = orb.object_to_string(objRef);
            Ch.Elca.Iiop.CorbaObjRef.Ior iorObj = new Ch.Elca.Iiop.CorbaObjRef.Ior(origObjData);
            CodeSetComponentData cscd = new CodeSetComponentData(
                (int)Ch.Elca.Iiop.Services.CharSet.UTF8,
                new int[] { (int)Ch.Elca.Iiop.Services.CharSet.UTF8 },
                (int)Ch.Elca.Iiop.Services.WCharSet.UTF16,
                new int[] { (int)Ch.Elca.Iiop.Services.WCharSet.UTF16 });
            omg.org.IOP.TaggedComponent codesetcomp = new omg.org.IOP.TaggedComponent(
                omg.org.IOP.TAG_CODE_SETS.ConstVal, m_codec.encode_value(cscd));
            iorObj.Profiles[0].TaggedComponents.AddComponent(codesetcomp);
            string newObjData = iorObj.ToString();
            MarshalByRefObject newObj = (MarshalByRefObject)orb.string_to_object(newObjData);
            ILicenseInfo li = (ILicenseInfo)newObj;
    ...
        }
    

    Unfortunately in my case the problem remained that the byte ordering was backwards too, so I had to go with an entirely different solution based on just getting bytes back and manually converting them to a string instead of getting string directly.