这是我第一次尝试为 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 的调用都会导致崩溃,也不异常(exception)。我感觉它是返回类型,但是如何在 C# 中正确地编码(marshal)它?
最佳答案
如果您以字符串
形式返回,则编码器将在返回的指针上调用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
?对于这个无参数函数来说没有什么区别,但不久你就会传递参数,你需要知道。
关于c# - 调用 C DLL 函数以从类型定义的 char 编码字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14926036/