1. achuta twameva
  2. PowerBuilder
  3. Saturday, 25 January 2020 09:31 AM UTC

Hi all,

I am facing a strange issue while fetching an array of a specific object type from .NET C# to PB 11.2 (classic) via COM.

My C# code is as follows:

namespace RestHandler
{
    [ComVisible(true)]
    [Guid("3CF8AB49-5E7D-4719-B277-5047C6A42FAE")]
    public interface IReturnArray
    {
        String getString();
        String[] getStringArray();
        myClass getClass();
        myClass[] getClassArray();
    }

    [ComVisible(true)]
    [Guid("EDA88A40-73BC-4e61-B134-DD07D42E91E0")]
    public class myClass
    {
        [ComVisible(true)]
        [MarshalAs(UnmanagedType.BStr)]
        public string myString;


        [ComVisible(true)]
        public int myInt;
    }

    [ComVisible(true)]
    [Guid("8035E886-82F1-47c7-AE7D-087DD0A555CE")]
    [ClassInterface(ClassInterfaceType.None)]
    public class ReturnArray : IReturnArray
    {
        public ReturnArray()
        {
        }
        public String getString()
        {
            return "Hello World";
        }
        public String[] getStringArray()
        {
            String[] myArray = new String[2] { "Hello", "World" };
            return myArray;
        }
        public myClass getClass()
        {
            myClass temp =
                new myClass
                {
                    myString = "Hello",
                    myInt = 1
                };
            return temp;
        }
        public myClass[] getClassArray()
        {
            myClass[] myArray =
                new myClass[]{
                    new myClass(){
                        myString = "Hello",
                        myInt = 1
                    },
                    new myClass(){
                        myString = "World",
                        myInt = 2
                    },
                    new myClass(){
                        myString = "This is Bruce",
                        myInt = 3
                    }
               };
            return myArray;
        }
    }
}

My PB code is as follows:

oleobject      retarray
int                    li_rc
int                    li_index, li_count
int                    li_x
String               ls_string
String               ls_stringarray[]
oleobject          loo_class
oleobject          loo_classarray[]

retarray = CREATE OleObject
li_rc = retarray.ConnectToNewObject ( "RestHandler.ReturnArray" )

ls_string = retarray.getString()
MessageBox ( "getString", ls_string )

ls_stringarray = retarray.getStringArray()
MessageBox ( "getStringArray", ls_stringarray[1] )

loo_class = retarray.GetClass()
MessageBox ( "GetClass", String ( loo_class.myString )) /*single object works*/
Destroy loo_class

loo_classarray = retarray.GetClassArray()
st_1.Text = loo_classarray[1].myString /*null error, array of object does not work?*/

retarray.DisconnectObject()

Destroy retarray

This is all Bruce Armstrong sample codes on some other forum. In there, it's mentioned this works. Strangely, when I return a single object from C#, I can access it via a corresponding OLEObject in PB. Now, when I return an array of an object (Employee[]), I am trying to convert that into an array of OLEObject in PB and the number of objects in this OLEObject array is indeed correct in PB. However, all the OLEObject within this array is null; therefore I am getting a null reference exception in PB at the following line:

st_1.Text = loo_classarray[1].myString /*null error, array of object does not work?*/

Does anyone here have any idea why? I have already spent hours trying to find the reason.

Thanking you in advance,

-A

Accepted Answer
Michael Kramer Accepted Answer Pending Moderation
  1. Saturday, 25 January 2020 17:56 PM UTC
  2. PowerBuilder
  3. # Permalink

Hi, let me try to explain what's going on:

  • You have COM access to one "complex" .NET object (let's call this object A)
  • That provides no automatic COM access to all other "complex" .NET objects referenced by object A
  • Your COM access however usually provides COM access to properties of simple datatypes

Your case:

  • Your "complex" object A is your array
  • It holds references to several other "complex" .NET objects
  • COM access to object A provides no automatic COM access to any referenced "complex" .NET object.
  • COM access however provides access to the Count = size of array since int is a simple datatype.

You may implement and expose function like GetObjectAtIndex(int idx) on your array class returning a COM accessible reference to the "complex" .NET object at index number idx.

HTH /Michael
NOTE: There may be nuances that are over-simplified in my description. I simplified to focus on the important issue = COM access to referenced "complex" objects.

 

Comment
  1. achuta twameva
  2. Sunday, 26 January 2020 23:58 PM UTC
Thanks Michael for the reply, I verified your suggestion and that seems to work.

I am still not sure why in the link below Bruce Armstrong says that looping through the array of OLEObjects from C# work.



https://answers.sap.com/questions/11023590/release-memory-after-call-to-net-com-object-via-ol.html



Thanks again,

-A
  1. Helpful
  1. Michael Kramer
  2. Monday, 27 January 2020 01:34 AM UTC
It may look like minute details - however, there is a great difference between string[ ], OLEObject[ ] each access to myObject containing a string, OLEObject access to string[ ], and OLEObject access to myObject[ ] each containing string. "Minor detail; major impact". I wouldn't know if I hadn't tried and had code blow up myself; then learned why. "Each error is an unexpected learning opportunity; not a failure."

  1. Helpful
There are no comments made yet.


There are replies in this question but you are not allowed to view the replies from this question.