[英]C++ string to C# using a struct
有没有办法使用结构将字符串从 C++ 发送到 C#? 我有一个包含图像数据(数据和大小)的结构,在这个结构中我也想从图像中获取条形码数据。 我试图通过 C# 中的 IntPtr 来做到这一点,但是通过 Stringbuilder 返回胡言乱语,但随后无法对结构进行编组。 有关所有相关代码,请参见下文
C# 结构
public struct ImageInfo
{
public IntPtr data; // image data, works
public int size; // image data, works
// string
//public IntPtr barcodeType; // return gibberish
//public IntPtr barcodeData; // return gibberish
public StringBuilder barcodeType; //Cannot marshal field 'barcodeType' of type 'ImageProcessingOpenCv.ImageInfo'
public StringBuilder barcodeData; //Cannot marshal field 'barcodeData' of type 'ImageProcessingOpenCv.ImageInfo'
}
C# 导入:
[DllImport("AlgorithmsCpp.dll", EntryPoint = "ScanBarcode", ExactSpelling = false, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern void ScanBarcode(byte[] data, int dataLen, ref ImageInfo imTemplate);
调用 C++ 以及我如何尝试从 IntPtr 获取字符串:
ImageInfo imInfo = new ImageInfo();
AlgorithmCpp.ScanBarcode(sourceImagePixels, sourceImagePixels.Length, ref imInfo); // wont work with StringBuilder.
string stringa = Marshal.PtrToStringAnsi(imInfo.barcodeType); // result: gibberish
stringa = Marshal.PtrToStringAuto(imInfo.barcodeType); // result: gibberish
stringa = Marshal.PtrToStringBSTR(imInfo.barcodeType); // result: gibberish
stringa = Marshal.PtrToStringUni(imInfo.barcodeType); // result: gibberish
stringa = Marshal.PtrToStringUTF8(imInfo.barcodeType); // result: gibberish
// example what is returned: "\0\0\0\0\0\0\0\0\f\0\0\0"
C++结构:
struct ImageInfo
{
unsigned char* data;
int size;
// String
//unsigned char* barcodeType; // for IntPtr, return gibberish
//unsigned char* barcodeData; // for IntPtr, return gibberish
char* barcodeType; // for StringBuilder
char* barcodeData; // for StringBuilder
};
我如何尝试从 C++ 返回一个字符串
#define DllExport extern "C" __declspec(dllexport)
DllExport void ScanBarcode(unsigned char* data, int dataLen, ImageInfo& imInfo)
{
// do stuff to get barcode
// for IntPtr
std::string type = symbol->get_type_name();
std::string data = symbol->get_data();
imInfo.barcodeType = (unsigned char*)type.c_str();
imInfo.barcodeData = (unsigned char*)data.c_str();
// For StringBuilder
strcpy(imInfo.barcodeData, symbol->get_data().c_str());
strcpy(imInfo.barcodeType, symbol->get_type_name().c_str());
}
我希望通过上面的代码,我可以让您了解我尝试过的内容以及我想要的内容。 如果您需要任何进一步的信息,请告诉我,我会尽力提供。
C++ 代码是错误的。
imInfo.barcodeType = (unsigned char*)type.c_str();
imInfo.barcodeData = (unsigned char*)data.c_str();
c_str()
给你一个指向字符串开头的指针,是的。 你可以把它传递给一个函数,很好。 但是你不能退货! 谁拥有记忆? 它的寿命是多少? 什么时候解除分配? C++ 没有自动内存管理——你不能只返回对象和指针并期望它们神奇地工作。 你甚至不能依赖这种不良行为来产生错误,正如你刚刚看到的——你得到了垃圾; 有时你会得到正确的东西,有时会得到错误的东西,有时你会引入一个可怕的安全漏洞。
当ScanBarcode
返回时, type
和data
被销毁。 c_str()
返回的指针未指向您认为它指向的数据(无论c_str()
的内部实现如何)。 您需要将该数据复制到共享内存中,并确保它被正确释放。 在非托管世界中,传递内存并不是一件容易的事情。 这是最初设计托管系统和 C# 等语言的重要原因之一。
设计互操作并非易事。 从实际设计良好的 C API 中获取示例。 一个重要的事情就是返回字符串的长度,例如(这是非常罕见的,你想通过刚才char*
,而未同时指定长度,它是彻底疯了,这样做,如果你没有自己的内存中指出, )。 首先,决定应该由谁分配和释放内存(这通常应该是相同的)。
你已经可以看到这有点问题。 ImageInfo
由调用者分配。 但是char*
字段是由被调用者分配的! 没有办法合理地将对象的生命周期限制在 C++ 或 C# 端(同样,这不是 C# 的问题——C++ 调用者会遇到同样的问题)。 过去处理这种情况的通常方法是使用预先分配的缓冲区 - 也就是说, imInfo.barcodeType
不是指向字符串的指针,而是一个数组。 C# 结构将如下所示:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
struct ImageInfo
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=255 /* this must be synchronized with the C++ code! */)]
public string barcodeType;
}
C++ 端会做这样的事情(不要在生产代码中使用它,它几乎肯定在某种程度上是错误的 - 我的 C++ 非常生疏;咨询 C++ 程序员):
struct ImageInfo
{
char barcodeType[255];
}
if (type.barcodeType.length() < 254)
{
strcpy(imInfo.barcodeType, type.c_str());
}
同样,这是非常幼稚的,可能是错误的。 这只是为了展示一种可以在调用者和被调用者之间传递数据的方法。 多保重。
StringBuilder不是字符串。
将您的结构更改为:
public struct ImageInfo
{
public IntPtr data; // image data, works
public int size; // image data, works
// string
//public IntPtr barcodeType; // return gibberish
//public IntPtr barcodeData; // return gibberish
public string barcodeType;
public string barcodeData;
}
应该可以工作,因为编译器现在有一个已知的值(某种)类型,它可以传递给您的 C++ 结构。 StringBuilder 将不起作用,因为这是一个无法转换为字符串的对象,而编译器必须知道调用 .ToString() 方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.