2013-02-17 62 views
2

这是我第一次尝试创建一个C库封装到C库。该SDK是第三方,我的控制范围之外:调用一个C DLL函数来编组一个字符串从一个类型定义的字符

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#中编组?

+0

如果在[DllImport]和私有静态外部...之间添加[return:MarshalAs(UnmanagedType.LPStr)],它会工作吗? – bas 2013-02-17 21:07:59

+0

SDK_API是如何定义的? – 2013-02-17 21:15:55

+0

删除了我的答案,去戴维斯解决方案。我不完全确定,大卫似乎是:)。 – bas 2013-02-17 21:21:23

回答

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

+1

thx为更正更聪明+1(和足够酷,不要扔我-1) – bas 2013-02-17 21:22:00

+0

@bas没有probs的。阅读Jared的答案在这里获取更多信息:http://stackoverflow.com/questions/370079/pinvoke-for-c-function-that-returns-char – 2013-02-17 21:24:10

相关问题