【发布时间】:2020-03-26 22:23:19
【问题描述】:
有没有办法通过使用结构将字符串从 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());
}
我希望通过上面的代码,我已经让您了解我尝试了什么以及我想要拥有什么。如果您需要任何进一步的信息,请告诉我,我会尽力提供。
【问题讨论】:
-
@Fildor 阅读互联网寻找可能的解决方案。我多次看到 StringBuilder,所以我厌倦了。我不知道为什么我应该或不应该使用它。
-
对于
IntPtr方法,你将imInfo.barcodeType/Data分配给局部变量type/data内部指针,在函数退出时被删除,因此指向乱码。 -
每个specification
char *可以编组到string或StringBuilder -
@PavelAnikhouski 是的,没有意识到这一点。可能相关:stackoverflow.com/a/15274893/982149 或 stackoverflow.com/a/1450756/982149
-
@wes 看看 msdn samples,尝试用
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]装饰你的struct,因为你使用的是 ansi 字符串。或者在字符串字段中添加MarshalAs