Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.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
将C#字符串传递给C++;并通过C++;结果(字符串、字符*。无论什么)到C#_C#_C++_String_Interop - Fatal编程技术网

将C#字符串传递给C++;并通过C++;结果(字符串、字符*。无论什么)到C#

将C#字符串传递给C++;并通过C++;结果(字符串、字符*。无论什么)到C#,c#,c++,string,interop,C#,C++,String,Interop,我尝试了不同的方法,但我对Interop很生气 (此处字符串不是指可变类型,而是指“字符集合”): 我有一个非托管C++函数,它定义在一个DLL中,我试图从C ^中访问,这个函数有一个字符串参数和一个字符串返回值: string myFunction(string inputString) { } C++中的字符串应该是什么?还有C#1?DllImport需要哪些参数?< P>我知道这样做的唯一好方法是使用.NET C++ C++类编写一个.NETC++包类,调用你的C++代码。托管扩展中有

我尝试了不同的方法,但我对Interop很生气

(此处字符串不是指可变类型,而是指“字符集合”): 我有一个非托管C++函数,它定义在一个DLL中,我试图从C ^中访问,这个函数有一个字符串参数和一个字符串返回值:
string myFunction(string inputString)
{
}

<> C++中的字符串应该是什么?还有C#1?DllImport需要哪些参数?

< P>我知道这样做的唯一好方法是使用.NET C++ C++类编写一个.NETC++包类,调用你的C++代码。托管扩展中有一些函数可以将System.String转换为char*或任何其他类型的非托管字符串


<>基本上,您使用C++创建.NET类并从程序集公开它,并在内部调用该程序集,可以调用您的本机C++代码。另一种方法是使用P/Unjk向C++代码添加纯C函数,然后调用C代码中的C代码,并使C函数调用C++代码。这将起作用,但我倾向于尽量使用托管代码。

< P>将C++中的字符串传递到C语言的最大问题是内存分配。GC应该能够知道如何清理为此字符串分配的内存。由于C#拥有广泛的COm互操作支持,它确实知道COm BSTR以及如何分配和取消分配这些BSTR。因此,最简单的方法是在C++侧使用<代码> BSTR < /C> > C代码边>代码>字符串< /> >


注意,使用BSTR并不意味着您的函数必须通过COM公开。

我发现最有效的方法是更明确地说明这里发生了什么。在这种情况下,可能不建议使用字符串作为返回类型

一种常见的方法是让C++端通过缓冲区和缓冲区大小。如果它不够大,无法容纳GetString必须放入的内容,则会修改bufferSize变量以指示合适的大小。然后,调用程序(C#)会将缓冲区的大小增加到适当的大小

如果这是导出的dll函数(C++):

匹配的C#将如下所示:

void GetString( StringBuilder buffer, ref int bufferSize );
int bufferSize = 512;
StringBuilder buffer = new StringBuilder( bufferSize );
GetString( buffer, ref bufferSize );
因此,要在C#中使用它,您可以执行以下操作:

void GetString( StringBuilder buffer, ref int bufferSize );
int bufferSize = 512;
StringBuilder buffer = new StringBuilder( bufferSize );
GetString( buffer, ref bufferSize );
“字符串”返回值就是问题所在。P/Invoke封送拆收器将对返回的指针调用CoTaskMemFree()。除非在C/C++代码中使用CoTaskMemAlloc()来分配字符串缓冲区,否则这不会很好地工作。这是一件相当不寻常的事情


最好的解决方案是允许代码的调用者将指向缓冲区的指针和缓冲区长度作为参数传递给您。这样,所有内存分配都发生在一侧。史葛向您展示了如何做到这一点。

< P>我必须将Unicode C字符串转换成多字节表示,以便在C++中转换成char *(这是部分单向解决方案)

我发现以下内容非常有用

string st; 
IntPtr stPtr = Marshal.StringToHGlobalAnsi(st); 
// Do your thing in C++ 

Marshal.FreeHGlobal(stPtr); 

这可能效率低下,而且不是C#方式,我对C#还不熟悉。

这是正确的方法。请注意,您不必通过引用传递缓冲区大小。C/C++应该终止字符串,buffer.ToString()生成返回值。谢谢大家的回答。我在某个地方看到StringBuilder被用于输出字符串,但是我还需要把C++字符串传递给输入字符串。我应该用什么类型的?在C++方面,我已经把char *和c*边字符串放进去了,但是它不起作用。最后,我可以将输出“字符串”(C++端)定义为常量字符*?或者我必须有一个char*?@Smjert:如果你不改变它,使用const char*是一个很好的方法。这应该正好映射到C#端的字符串。你看到的是什么类型的问题?@nobugz:我会检查bufferSize是否不需要通过引用传递,并在找到答案时更新它。如果它确实不必是引用,那么这将是一个很好的提示,但我不确定我是否理解为什么会是这种情况。@Scott-P/Invoke封送处理程序明确支持以零结尾的字符串。它知道如何正确地将char*填充到StringBuilder中。只有当char*不是像通常的“C”字符串那样以零结尾时,才会出现问题。