使用结构将C ++字符串转换为C#

韦斯

有没有一种方法可以使用结构将字符串从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());
}

我希望上面的代码能使您了解我尝试过的东西和想要拥有的东西。如果您需要任何其他信息,请告诉我,我将尝试提供。

a安

C ++代码错误。

imInfo.barcodeType = (unsigned char*)type.c_str();
imInfo.barcodeData = (unsigned char*)data.c_str();

c_str()给您一个指向字符串开头的指针,是的。您可以将其传递给函数,很好。但是你不能退货谁拥有记忆?它的寿命是多少?什么时候释放?C ++没有自动内存管理功能-您不能只返回对象和指针并期望它们能够神奇地工作。正如您刚刚看到的那样,您甚至不能依靠这种不良行为来产生错误-您会得到垃圾;有时您得到正确的东西,有时得到错误的东西,有时您引入了可怕的安全漏洞。

到此为止ScanBarcodetype并被data摧毁。所返回的指针c_str()未指向您认为它指向的数据(无论的内部实现如何c_str())。您需要将该数据复制到共享内存中,并确保已正确释放它。在不受管理的世界中,传递内存并不是一件容易的事。这就是为什么首先设计托管系统和诸如C#之类的语言的重要原因之一。

设计互操作器并非无关紧要。以实际设计良好的C API为例。例如,重要的一件事是返回字符串的长度(非常罕见的是,您只需要传递just 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());
}

同样,这是非常幼稚的,并且可能是错误的。这只是为了展示一种通常可以处理在调用方和被调用方之间传递数据的方法。多保重。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

字符串转换为C#

来自分类Dev

C#:将字符列表转换为字符串

来自分类Dev

使用Roslyn将C#字符串值转换为转义的字符串文字

来自分类Dev

C#将字符串转换为字典

来自分类Dev

C#将字符串转换为整数

来自分类Dev

将c#字符串[]转换为json

来自分类Dev

将JSON字符串转换为C#字典

来自分类Dev

将字符串转换为double或float C#

来自分类Dev

C#将类转换为查询字符串

来自分类Dev

将字符串转换为列表-C#

来自分类Dev

C#将Double从DataGridView转换为字符串

来自分类Dev

将字符串转换为数组| C#

来自分类Dev

将字符串转换为C#

来自分类Dev

将JSON字符串转换为C#字典

来自分类Dev

将字符串转换为css c#

来自分类Dev

试图将字符串转换为双C#?

来自分类Dev

将字符串转换为JSON对象C#

来自分类Dev

将位字符串转换为byte [] c#

来自分类Dev

将字符串转换为JSON C#

来自分类Dev

将字符串转换为(对象)routeValues C#

来自分类Dev

将字符串转换为活动名称C#

来自分类Dev

C#将字符串值转换为字节

来自分类Dev

C#将字符串转换为JSON错误

来自分类Dev

WebDriver C# - 将 WebElement 转换为字符串

来自分类Dev

C#将字符串转换为int

来自分类Dev

C# 将字符串转换为 int 出错

来自分类Dev

将字符串转换为 int C#

来自分类Dev

C# 无法将类型转换为字符串

来自分类Dev

c# 将 json 字符串转换为 .csv