Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将常量wchar_t*从C DLL自动转换为C#字符串_C#_C++_Dll_Wchar T_Interopservices - Fatal编程技术网

如何将常量wchar_t*从C DLL自动转换为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

这只是一种好奇。也许这个世界上有一个人做过这样的事情:

我必须导出C函数并通过DllImport从C代码加载它

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