pushE
pushE

Reputation: 414

Handling Array returned from c++ dll to C#

I have this in my dll created in c++

extern "C" __declspec(dllexport)
    char*  __stdcall hh()
{
    char a[2];
    a[0]='a';
         a[1]='b';
    return(a);
}

And this is how I am trying to handle code in c#

[DllImport(@"mydll.dll",CharSet = CharSet.Ansi,CallingConvention = CallingConvention.StdCall)]     
       public static extern IntPtr hh();
       static void Main(string[] args)
        {
            IntPtr a = hh();
           //How to proceed here???
        }


    }

Help in proceeding further.

Upvotes: 5

Views: 4088

Answers (4)

pushE
pushE

Reputation: 414

I got a solution as follows::

OUR C++ code goes as follows

extern "C" __declspec(dllexport)
    char**  __stdcall hh()
{
 static char* myArray[3] = {"A1", "BB2", "CC3",};
    return myArray;
}

And C# goes as follows

[DllImport(@"ourdll.dll",CharSet = CharSet.Ansi,CallingConvention = CallingConvention.StdCall)]     
      public static extern IntPtr hh();
       static void Main(string[] args)
        {
            IntPtr a = hh();
            int j = 0;
            string[] s=new string[100];
           do
           {
               s[j] = Marshal.PtrToStringAnsi(Marshal.ReadIntPtr(a,4*j));
               j++;
           }
           while(s[j-1] != null);
        }

The only problem now faced is that how can we know size of the array so that in this statement string[] s=new string[100]; we neednot waste our memory.

Upvotes: 2

Konstantin Oznobihin
Konstantin Oznobihin

Reputation: 5327

There is no way to handle such arrays. char a[2] is allocated on the stack in your C++ function and is destroyed as soon as you return from it. You should either pass an array from C# and fill it in the C++ code or allocate array in the heap and provide some means for freeing it.

When you have it correct the handling will depend on how you return the data from C++ code. If it's still IntPtr you could use Marshal.ReadByte methods to read characters from memory and use Encoding methods to convert those bytes into string if necessary.


const int bufferSize = 2; // suppose it's some well-known value.
IntPtr p = ...; // get this pointer somehow.
for (var i = 0; i != bufferSize; ++i)
{
  var b = Marshal.ReadByte(p, i);
  Console.WriteLine(b);
}

Upvotes: 3

ervinbosenbacher
ervinbosenbacher

Reputation: 1780

The answer would be

 string stra = Marshal.PtrToStringAnsi(a);

But you also have the problem that the dll returns garbage per your code as char* is a local c style string. Would be ok if you would return something like:

 const char* str = "Hello from DLL.";

Upvotes: 1

Archeg
Archeg

Reputation: 8462

Try to use not empty StringBuilder as the return value.

Upvotes: -2

Related Questions