簡體   English   中英

將 c++ std::string 轉換為 c# 字節數組

[英]Convert c++ std::string to c# byte array

我有一個使用 DLL 導出來獲取用戶名的 .NET 程序。

public static extern string Name(byte[] buf);

這是導出,我真的不想改變它,因為很多代碼都依賴它。 所以,我想知道,在 C++ 中,如何將char*數組轉換為字節緩沖區?

我試過這個:

void Name(std::byte buf[256])
{
    std::string s{ "test" };
    std::byte* ptr = reinterpret_cast<std::byte*>(s.data());
    buf = ptr;
    return;
}

當我打印出我轉換的字符串時,我什么也沒得到,它是空的。

您的 C++ 函數實現與 C# 函數聲明的預期不符。

C# 字節數組作為指向數組原始內存的固定指針編組到函數中。 您在 C++ 代碼中使用的參數語法( std::byte buf[256] )只是語法糖,編譯器實際上將其視為指針( std::byte* buf )。 在這種情況下這很好。 但是,您的 C++ 函數實際上並未將任何內容復制到指針指向的內存中。 您只是將指針本身更改為指向不同的內存地址。 而且指針本身是一個局部變量,所以當函數退出時,指針將不復存在,指向什么也無所謂。

此外,C# 聲明期望函數返回可以編組為 .NET string的內容,但 C++ 函數實際上根本沒有return任何內容。 string返回值的默認編組行為是UnmanagedType.LPStr ,因此 C++ 函數需要返回一個指向以 null 結尾的char*字符串的指針。 該字符串的內存必須使用CoTaskMemAlloc()分配,因為編組器將獲取內存的所有權並在將char數據轉換為string后使用CoTaskMemFree()釋放它。

此外,C++ 函數沒有定義調用約定,因此它將使用編譯器的默認值(通常是__cdecl ,除非您更改編譯器的設置)。 但是,.NET 的DllImport期望 C++ 函數使用的默認調用約定是__stdcall (為了與 Win32 API 兼容)。 這種不匹配在 64 位中無關緊要,但在 32 位中很重要。

在不更改 C# 聲明的情況下,在 C++ 端嘗試此操作:

char* __stdcall Name(std::byte buf[256])
{
    std::string s{ "test" };
    size_t size = s.size() + 1;
    memcpy(buf, s.c_str(), size);
    void *ptr = CoTaskMemAlloc(size);
    memcpy(ptr, s.c_str(), size);
    return ptr;
}

話雖如此,有一個函數在字節數組輸出參數和返回值中都返回一個字符串是很奇怪的。 您確定字節數組不打算用作輸入參數,而是函數解析其內容以提取字符串? 那會更有意義。 如果您更新您的問題以顯示您的 .NET 代碼如何實際調用 C++ 函數並使用字節數組,這將非常有幫助。

當你寫

void Name(std::byte buf[256])

buf聲明為指向 256 字節的指針,而不是數組。 所以當你以后寫

buf = ptr;

您所做的只是將局部變量buf更改為現在指向ptr 並且在函數結束時局部變量死亡。

使用std::array<std::byte, 256>&並將字符串內容復制到其中。 或者甚至更好地返回一個新制作的數組而不是一個輸入/輸出參數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM