将C++字符返回到C#
本文关键字:返回 字符 C++ | 更新日期: 2023-09-27 18:25:04
我有一个C++项目,其中我必须将一些变量从C++返回到C#。
这些字符变量在主程序中:
char test1[MAX_Q_LEN],test2[MAX_Q.LEN],test3[MAX_Q-LEN];
在我的C程序中完成对这些变量的处理之后,我必须在C#程序中返回这些变量的值。
ReturnChar.h
extern "C" RETURNCHAR_API TCHAR* __cdecl testString();
ReturnChar.cpp
extern "C" RETURNCHAR_API TCHAR* testString()
{
return ;
}
测试导入C#
static class TestImport
{
[DllImport("MyDLL.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr testString();
}
public partial class MainWindow : Window
{
public MainWindow()
{
try
{
InitializeComponent();
textBox1.Text = ReturnSomething()
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private static string ReturnSomething()
{
IntPtr t = TestImport.testString();
String result = Marshal.PtrToStringAuto(t);
}
我尝试了上面的方法,但我找不到如何返回上面的char值。此外,这不应该是一个独立的函数,因为只有在执行main之后才能获取值,main将在这些变量中给出正确的值。
有什么建议吗?
我将建议一个需要将函数签名更改为以下内容的解决方案:
extern "C" int __cdecl testString(char *output, int outputSize);
也就是说,将分配的缓冲区作为第一个参数传递给将保存输出的函数,并将缓冲区的大小作为第二个参数传递。
注意,我提到函数的返回类型为int
。这是因为您可以从函数返回输出实际大小,并且调用者可以解释该值以确认outputSize
值足够大,可以容纳输出字符串。例如,您可以将testString()
实现为:
int testString(char *output, int outputSize)
{
std::string const & s = getString();
if ( s.size() <= outputSize )
{
std::strncpy(output, s.c_str(), s.size());
return s.size(); //return the actual size of output
}
else //means s.size() > outputSize, i.e outputSize is smaller than required!
{
std::strncpy(output, s.c_str(), outputSize);
return s.size(); //return what is required (the actual size of output)!
}
}
然后在C#代码中,这样做:
[DllImport("MyDLL.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern int testString(out StringBuilder output, int outputSize);
并称之为:
private static string ReturnSomething()
{
int bufferSize = 100;
StringBuilder buffer= new StringBuilder(bufferSize);
int outputSize = TestImport.testString(buffer, bufferSize);
if ( outputSize < bufferSize ) //output bufferSize was sufficient
{
return buffer.ToString();
}
else //output bufferSize was insufficient
{
//retry!
bufferSize = outputSize;
buffer = new StringBuilder(bufferSize); //reallocate!
outputSize = TestImport.testString(buffer, bufferSize);
if ( outputSize <= bufferSize )
return buffer.ToString();
else
{
throw new Exception("PANIC");
}
}
}
我不是很喜欢c++规范,但可能在c++中使用bstr
_bstr_t text("saasas");
return text.Detach();
对于c#参数
[MarshalAs(UnmanagedType.BStr)]
或者将StringBuilder
传递给具有一些预分配容量的c++函数