tags:

views:

272

answers:

2

Hello,

I have a the following C++ function

void FillAndReturnString(char ** someString)
{
   char sourceString[] = "test";
   *someString = new char[5];
   memcpy(*someString, sourceString, 5);   
}

It is declared as

extern "C"
{
__declspec(dllexport) void __cdecl FillAndReturnString(char ** someString);
}

How do I call this function from C#?

Thanks

+3  A: 

With P/Invoke.

Max Lybbert
That's not terribly specific.
sblom
No, it's not. But the original question didn't say what he had already tried and what problems he had run into, so I really can't get more specific. But the tutorial I linked to does go into details.
Max Lybbert
A: 

You need to know that you're allocating unmanaged memory block in your c++ function, so it will not be possible to pass a managed String or Array object from C# code to 'hold' the char array.

One approach is to define 'Delete' function in your native dll and call it to deallocate the memory. On the managed side, you can use IntPtr structure to temporarily hold a pointer to c++ char array.

// c++ function (modified)
void __cdecl FillAndReturnString(char ** someString)
{
   *someString = new char[5];
   strcpy_s(*someString, "test", 5);   // use safe strcpy
}

void __cdecl DeleteString(char* someString)
{
   delete[] someString
}


// c# class
using System;
using System.Runtime.InteropServices;

namespace Example
{
   public static class PInvoke
   {
      [DllImport("YourDllName.dll")]
      static extern public void FillAndReturnString(ref IntPtr ptr);

      [DllImport("YourDllName.dll")]
      static extern public void DeleteString(IntPtr ptr);
   }

   class Program
   {
      static void Main(string[] args)
      {
         IntPtr ptr = IntPtr.Zero;
         PInvoke.FillAndReturnString(ref ptr);

         String s = Marshal.PtrToStringAnsi(ptr);

         Console.WriteLine(s);

         PInvoke.Delete(ptr);
      }
   }

}

Kei
You can also use char* in C#(not CLI compliant but you can do more with a typed pointer then you can with an IntPtr) but only if you are using wchar_t in the c++ side. And its really not important that holding the variable is only temporary. Certainly if you leave unmanaged memory laying around in a managed object you will have to be aware of it and delete when appropriate but there is nothing special about it as far as the CLR is concerned.
Hippiehunter
This blows up atPInvoke.FillAndReturnString(ref ptr)
MHM
MHM - Is any exception thrown? If so, what does the error say? Please make sure that c++ code is surround by extern "C", and the c++ .dll is at the same location as the c# .exe. And, there is a good chance that I missed something in my code, of course..
Kei