调用一个C DLL函数来封送来自类型定义字符的字符串

本文关键字:类型 定义 字符串 字符 函数 一个 DLL 调用 | 更新日期: 2023-09-27 17:59:42

这是我第一次尝试为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#中正确地整理它?

调用一个C DLL函数来封送来自类型定义字符的字符串

如果返回为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_API是什么。它是stdcall还是cdecl?这个无参数函数没有什么区别,但不久之后你就会传递参数,你需要知道。