2

これは、CライブラリへのC#ラッパーを作成する最初の試みです。SDKはサードパーティであり、私の管理外です。

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);

私のC#ラッパー:

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

sdk_get_versionを呼び出すと、例外なくクラッシュが発生します。リターンタイプだと思いますが、C#で適切にマーシャリングするにはどうすればよいですか?

4

1 に答える 1

2

として戻ると、マーシャラーは返されたポインターをstring呼び出します。CoTaskMemFreeそれがあなたに起こっていることであり、あなたのコードが失敗する理由だと思います。そのAPIを見ると、返されるポインタはDLL内の文字列リテラルを指している可能性が高く、確かに。で割り当てられたものではありませんCoTaskMemAlloc

IntPtrしたがって、それをとして返し、を使用して文字列に変換する必要がありますMarshal.PtrToStringAnsi

したがって、次のように必要です。

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

....

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

さらに先に進む前に、何であるかを理解する必要がありますSDK_APIstdcallそれですか、cdeclそれともですか?このパラメータなし関数には違いはありませんが、やがてパラメータを渡すことになり、知る必要があります。

于 2013-02-17T21:14:34.370 に答える