0

I have dll with function:

extern "C"
int
doJob(char** buffer);

Its usage with C++ looks like this:

char* buf;
int status = doJob(&buf);

What definition should I have for this function in C#? How can I use this function in C#?

1 Answers1

0

One of the possible patterns is:

[DllImport("containsdojob.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 doJob(out IntPtr buffer);

[DllImport("containsdojob.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void freeMemory(IntPtr buffer);

and

IntPtr buffer = IntPtr.Zero;
string str = null;

try
{
    doJob(out buffer);

    if (buffer != IntPtr.Zero)
    {
        str = Marshal.PtrToStringAnsi(buffer);
    }
}
finally
{
    if (buffer != IntPtr.Zero)
    {
        freeMemory(buffer);
    }
}

Note that you'll need a freeMemory method to free the memory allocated by doJob.

There are other possible patterns, for example based on BSTR and SysAllocString that are easier to implement C#-side (but more difficult to implement C-side)

The "pattern" for using BSTR:

C-side:

char *str = "Foo"; // your string
int len = strlen(str);
int wslen = MultiByteToWideChar(CP_ACP, 0, str, len, 0, 0);
BSTR bstr = SysAllocStringLen(NULL, wslen);
MultiByteToWideChar(CP_ACP, 0, str, len, bstr, wslen);
// bstr is the returned string

C#-side:

[DllImport("containsdojob.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 doJob([MarshalAs(UnmanagedType.BStr)] out string buffer);

string str;
doJob(out str);

The memory is automatically handled (freed) by the CLR.

If you are using Visual C++ you can even

char *str = "Foo"; // your string
_bstr_t bstrt(str);
BSTR bstr = bstrt.Detach(); 
// bstr is the returned string

Or C-side you could use one of the two allocators that can be freed C#-side: LocalAlloc or CoTaskMemAlloc:

char *str = "Foo"; // your string
char *buf = (char*)LocalAlloc(LMEM_FIXED, strlen(str) + 1);
// or char *buf = (char*)CoTaskMemAlloc(strlen(str) + 1);
strcpy(buf, str);
// buf is the returned string

Then you use the first example, but instead of calling

freeMemory(buffer);

you call:

Marshal.FreeHGlobal(buffer); // for LocalAlloc

or

Marshal.FreeCoTaskMem(buffer); // for CoTaskMemAlloc
xanatos
  • 109,618
  • 12
  • 197
  • 280