2

This is my first attempt at creating a C# wrapper to a C lib. The SDK is 3rd party and outside my control:

sdk_defines.h

#ifndef SDK_CHAR_T
#define SDK_CHAR_T
typedef char sdk_char_t;
#endif /* SDK_CHAR_T */

#ifndef SDK_CSTR_T
#define SDK_CSTR_T
typedef const sdk_char_t*  sdk_cstr_t;
#endif /* SDK_CSTR_T */

sdk.h

sdk_cstr_t SDK_API
sdk_get_version(void);

My C# wrapper:

[DllImport("sdk.dll", CharSet = CharSet.Ansi)]
private static extern string sdk_get_version();

Any call to sdk_get_version causes a crash, no exception. I have a feeling it's the return type, but how do I properly marshal it in C#?

mbursill
  • 2,911
  • 1
  • 32
  • 44

1 Answers1

2

If you return as string, then the marshaller will call CoTaskMemFree on the pointer that is returned. I expect that's what's happening to you and is why your code fails. Looking at that API it seems most likely that the pointer that is returned points to a string literal in the DLL, certainly not something allocated with CoTaskMemAlloc.

So, you are going to need to return that as an IntPtr and then convert to string using Marshal.PtrToStringAnsi.

So you need it like this:

[DllImport("sdk.dll")]
private static extern IntPtr sdk_get_version();

....

IntPtr ptr = sdk_get_version();
string version = Marshal.PtrToStringAnsi(ptr);

Before you go much further you need to work out what SDK_API is. Is it stdcall or is it cdecl? It makes no difference for this no-parameter function, but before long you'll be passing parameters, and you'll need to know.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • 1
    thx for the corrections +1 for being smarter (and cool enough to not throw me on -1 :)) – bas Feb 17 '13 at 21:22
  • @bas No probs at all. Read Jared's answer here for more info: http://stackoverflow.com/questions/370079/pinvoke-for-c-function-that-returns-char – David Heffernan Feb 17 '13 at 21:24