【问题标题】:Convert string to char* to string (C# -> C -> C++)将字符串转换为 char* 到字符串 (C# -> C -> C++)
【发布时间】:2018-09-02 00:28:52
【问题描述】:

我正在开发一个带有 C 包装器的 C++ DLL,以便能够在不同的语言上使用它。目前,我也在用 C# 开发一个调用我的 DLL 的插件。

我想要传递一个字符串(文件的路径)作为我的 DLL 的参数,以便能够在我的 DLL 上使用它。

C#

[DllImport(DllName, CallingConvention = DllCallingConvention)]
public static extern IntPtr AllocateHandle(string filename);

C 包装器

LPVOID SAMPLEDLL_API CALLCONV_API AllocateHandle(char* filename);

C++ 类构造函数

CustomData::CustomData(char* filename)
{
    _filename = filename; // string _filename;
}

当我将 _filename 保存在文件上时(因为我没有找到在 DLL 上使用断点进行调试的方法),我有类似 ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ0à× 的东西。我尝试了不同的解决方案将 char* 转换为字符串,但结果仍然相同。

提前感谢您的帮助。

【问题讨论】:

  • 我想你需要用[MarshalAs(UnmanagedType.LPStr)]装饰你的filename
  • 第一次评论没有,对不起,我发现了 DLL、插件等的世界,所以 MarshalAs 目前对我没有任何意义,我更愿意在此之前尝试第一个答案,它正在工作,所以谢谢都一样

标签: c# c++ c string type-conversion


【解决方案1】:

看起来您将从托管代码传递的字符串存储在非托管类的成员字段中。那是行不通的,因为垃圾收集器会在某个时候移动或处置托管字符串,这将使字符串在非托管端变得无用。如果要保留字符串以供以后使用,则必须在非托管端(在非托管堆上分配)复制它。

CustomData::CustomData(char *filename)
{
  // _filename will need to be freed at some point; might
  // want to think about using std::string instead
  // like _filename = new std::string (filename);
  _filename = strdup(filename);
}

现在非托管代码拥有自己的(非托管)字符串副本,因此当 GC 处理托管字符串时,这无关紧要。这是处理这种情况的最简单方法,因为您也在编写非托管代码。还有其他措施可以防止 GC 干扰非托管互操作,但这些措施既棘手又耗时,并且只有在您无法修改非托管代码时才需要。

【讨论】:

  • 这比你第一段描述的还要糟糕,因为用于互操作的缓冲区可以在与之关联的托管字符串之前很久就被垃圾收集。
【解决方案2】:

问题是 C# 中的字符串是 Unicode。 cpp中的字符串是ansi字符串。你必须告诉 C# 字符串必须是 ansi:

[DllImport(DllName.dll, CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Ansi)]
static extern IntPtr AllocateHandle(string filename);

您还可以将字符串长度作为第二个参数传递,这样您就可以知道 cpp 端的字符串长度是多少。

[编辑]

根据某些 cmets,您还可以尝试将 [char *] 更改为 unicode 的 [wchar_t *]。那么你当然应该在 C# 端使用适当的属性: CharSet=CharSet.Unicode

【讨论】:

  • 不是默认Ansi吗? msdn.microsoft.com/en-us/library/…
  • 默认的 dll 导入字符串封送处理是 ANSI,我最好在 dll 中使用wchar_t
  • @Bigiansen Ansi 是一个 1-byte per-char 并且 Unicode 使用 2-bytes 来表示字符串中的字符,如果 op 想要使用非英文字符,它们应该是 unicode
  • msdn.microsoft.com/en-us/library/4bb3e64h.aspx - 这表明只有某些语言支持多字节字符串。比如日语或者中文。通常 ANSI 是每个字符一个字节。 Unicode 字符集更宽。在 unicode 中,每种语言的每个字符都用多个字节编码。 UTF8 每个字符可以有 1 到 4 个字节。
  • CharSet.Unicodewchar_twchar_t * convert to string 一起使用,现在可以使用了,谢谢;)
猜你喜欢
  • 2012-01-16
  • 2018-03-27
  • 2013-05-13
  • 1970-01-01
  • 2010-11-22
  • 1970-01-01
  • 2011-02-03
  • 2019-04-14
  • 1970-01-01
相关资源
最近更新 更多