0

I am trying to import the following:

const char * const *object_get_prop_names(propobject_t *ocr);

as:

[DllImport("vender.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private static extern IntPtr object_get_prop_names(int* osr);

based on: https://limbioliong.wordpress.com/2011/08/14/returning-an-array-of-strings-from-c-to-c-part-1/

I've tried the following:

var pNames = object_get_prop_names(hdl);

int StringCount = 200; //how do I know string count?

IntPtr[] pIntPtrArray = new IntPtr[StringCount];
ManagedStringArray = new string[StringCount];

Marshal.Copy(pNames, pIntPtrArray, 0, StringCount);

for (int i = 0; i < StringCount; i++)
{
    ManagedStringArray[i] = Marshal.PtrToStringAnsi(pIntPtrArray[i]);
    //Marshal.FreeCoTaskMem(pIntPtrArray[i]); crashes
}

//Marshal.FreeCoTaskMem(pUnmanagedStringArray); crashes

This works but I am guessing that I have memory leaks and accessing memory I shouldn't.

How should I free the memory?

How do I know the count? This is from a vendor and they will not modify the dll for little ol' me. :)

Also forgive me for delving into something I know very little about.

2
  • 1
    It returns const char* so there is not much reason to worry about releasing the strings. There must be some kind of way to find out how many strings there are. I'd look for IntPtr.Zero or an empty string. You can't use Marshal.Copy() safely until you know, use Marshal.ReadIntPtr() for each element, incrementing pNames by IntPtr.Size each time. Commented Nov 10, 2017 at 23:45
  • @Hans That worked! I read until I get a null. Can you write up the solution so I can give you credit? Commented Nov 10, 2017 at 23:56

1 Answer 1

2

Following Hans' suggestions:

var pNames = object_get_prop_names(hdl);
if (h == IntPtr.Zero)
{
    return null;
}

var nameList = new List<string>();
int elementSize = Marshal.SizeOf(typeof(IntPtr));

for (int i = 0; i < 200; i++) //don't know length, pick large number
{
    var ptr = Marshal.ReadIntPtr(pNames, i * elementSize);
    var str = Marshal.PtrToStringAnsi(ptr);
    if (!string.IsNullOrWhiteSpace(str))
    {
        nameList.Add(str);
    }
    else //end of pNames
    { 
        break; 
    }
}

Works great. I have no way of knowing how many property names there are so I just have to pick a larger number than the possible number of property names.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.