将字符串转换为字符*转换为字符串(C&>;C->;C&>;C&>;x2B;&&x2B;) 我正在使用一个C包装器的C++ DLL来在不同的语言上使用它。现在,我正在开发一个C#插件,它调用我的DLL

将字符串转换为字符*转换为字符串(C&>;C->;C&>;C&>;x2B;&&x2B;) 我正在使用一个C包装器的C++ DLL来在不同的语言上使用它。现在,我正在开发一个C#插件,它调用我的DLL,c#,c++,c,string,type-conversion,C#,C++,C,String,Type Conversion,我想要的是传递一个字符串(文件的路径)作为DLL的参数,以便能够在DLL上使用它 C# C包装器 LPVOID SAMPLEDLL_API CALLCONV_API AllocateHandle(char* filename); CustomData::CustomData(char* filename) { _filename = filename; // string _filename; } C++类构造函数 LPVOID SAMPLEDLL_API CALLCONV_API

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

C#

C包装器

LPVOID SAMPLEDLL_API CALLCONV_API AllocateHandle(char* filename);
CustomData::CustomData(char* filename)
{
    _filename = filename; // string _filename;
}
C++类构造函数

LPVOID SAMPLEDLL_API CALLCONV_API AllocateHandle(char* filename);
CustomData::CustomData(char* filename)
{
    _filename = filename; // string _filename;
}
当我将文件名保存到一个文件中时(因为我没有找到在DLL上使用断点进行调试的方法),我有一些类似于
。我尝试了不同的解决方案将char*转换为字符串,但结果仍然相同


提前感谢您的帮助。

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

[DllImport(DllName.dll, CallingConvention=CallingConvention.StdCall, CharSet=CharSet.Ansi)]
static extern IntPtr AllocateHandle(string filename);
您还可以传递字符串长度作为第二个参数,这样您就可以知道cpp端的字符串长度

[编辑]


根据一些评论,您还可以尝试将[char*]更改为[wchar\u t*],即unicode。然后您当然应该在C#side上使用approveriate属性:CharSet=CharSet.Unicode它看起来像是将托管代码传递的字符串存储在非托管类的成员字段中。这是行不通的,因为垃圾收集器将在某个时候移动或处理托管字符串,这将使该字符串在非托管端变得无用。如果要保留该字符串供以后使用,则必须在非托管端(在非托管堆上分配)复制该字符串


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

有帮助吗?我想您需要用
[MarshalAs(UnmanagedType.LPStr)]修饰
文件名
第一条评论是否定的,很抱歉我发现了DLL、插件等的世界,所以MarshalAs现在对我来说没有任何意义,我更愿意在这之前尝试第一个答案,它正在工作,所以谢谢大家,这不是默认的
Ansi
?默认的dll导入字符串封送是ANSI,我建议在dll@BigiansenAnsi是每个字符1字节,Unicode使用2字节来表示字符串中的字符,如果op希望使用英语以外的字符,则应使用Unicode-这表明只有某些语言支持多字节字符串。例如日语或汉语。通常ANSI是每个字符一个字节。Unicode字符集更宽。在unicode中,每种语言中的每个字符都用多个字节编码。UTF8每个字符最多可以有一个字节。使用
CharSet.Unicode
wchar\u t
,它现在可以工作了,谢谢;)这比第一段描述的还要糟糕,因为用于互操作的缓冲区可以在与之关联的托管字符串之前很久被垃圾收集。