如何将常量wchar_t*从C DLL自动转换为C#字符串
这只是一种好奇。也许这个世界上有一个人做过这样的事情: 我必须导出C函数并通过DllImport从C代码加载它如何将常量wchar_t*从C DLL自动转换为C#字符串,c#,c++,dll,wchar-t,interopservices,C#,C++,Dll,Wchar T,Interopservices,这只是一种好奇。也许这个世界上有一个人做过这样的事情: 我必须导出C函数并通过DllImport从C代码加载它 const wchar_t * SysGetLibInfo() { return dllmanager.SysGetLibInfo(); } 最好的方法是声明IntPtr,然后使用一些函数将其转换为字符串,这也是广泛推荐的方法。换句话说,像这样的事情 [DllImport(dll, CallingConvention = CallingConvention.Cdecl)] p
const wchar_t * SysGetLibInfo() {
return dllmanager.SysGetLibInfo();
}
最好的方法是声明IntPtr,然后使用一些函数将其转换为字符串,这也是广泛推荐的方法。换句话说,像这样的事情
[DllImport(dll, CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SysGetLibInfo();
// ...
Marshal.PtrToStringUni(SysGetLibInfo());
这种方法有效。但有没有一种方法可以自动做到这一点?要使SysGetLibInfo返回字符串?我发现一些建议如下:
[DllImport(dll, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPWStr)]
private static extern string SysGetLibInfo();
但是它不起作用,而且,根据各种各样的例子和稀少的报告,它不应该起作用
有没有一种方法可以编写我自己的属性,比如MarshalAs,它可以将IntPtr转换为string?类似于此:
[DllImport(dll, CallingConvention = CallingConvention.Cdecl)]
[return: MyOwnMarshalPtrToStringUni]
private static extern string SysGetLibInfo();
提前感谢您提供的任何信息或有用的链接、示例、书籍。同样,这只是一种好奇
另外,建议使用单独的函数包装SysGetLibInfo,该函数使用PtrToStringUni将结果转换为字符串,这不是一个选项;) 我认为问题在于
LPWStr
:
除非
字符串是使用非托管CoTaskMemAlloc函数创建的
这个很好用。本机代码:
// header
extern "C" __declspec(dllexport) wchar_t* SysGetLibInfo(void);
// implementation
extern "C" __declspec(dllexport) wchar_t* SysGetLibInfo(void)
{
return TEXT("Hello from unmanaged world!");
}
托管代码:
[DllImport("NativeLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPTStr)]
static extern string SysGetLibInfo();
如果要以这种方式更改本机函数:
extern "C" __declspec(dllexport) wchar_t* SysGetLibInfo(void)
{
wchar_t* pStr = (wchar_t*)CoTaskMemAlloc(100);
ZeroMemory(pStr, 100);
wcscpy(pStr, TEXT("Hello from unmanaged world!"));
return pStr;
}
然后
[return:marshallas(UnmanagedType.LPWStr)]
也会起作用。您不能覆盖marshallas,但可以使用自定义编组
谢谢,这是一个选择。实现ICustomMarshaler接口比实现ICustomMarshaler接口更简单,是吗?标准字符串类型的自定义封送拆收器?闻起来像另一个轮子。要允许此“[return:marshallas(UnmanagedType.CustomMarshaler,MarshalTypeRef=typeof(MyMarshaller))”,我需要创建实现ICustomMarshaler接口的类MyMarshaller,对吗?在MyMarshaller#MarshallNativeToManaged中,我将使用PtrToStringUni。。。。或者你的意思是有一个标准类已经做到了这一点?谢谢!不幸的是,我不想这样做。让我们假设DLL已经被写入,并且它返回常量wchar\u t*:)。非常感谢你!让我们假设DLL已经编写好了,所以在封送处理时使用
LPTStr
。这在两种情况下都有效(有CoTaskMemAlloc
和没有它)。这里不需要自定义封送拆收器。LPTStr不工作,有时会调用System.AccessViolationException。根据MS文档,没有什么特别之处
[DllImport(dll, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(MyMarshaller))]
private static extern string SysGetLibInfo();