[英]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.