简体   繁体   English

将 c++ std::string 转换为 c# 字节数组

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

I have a .NET program that uses a DLL export to get a name of a user.我有一个使用 DLL 导出来获取用户名的 .NET 程序。

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

This is the export, and I would really like to not change it, as a lot of code relies on it.这是导出,我真的不想改变它,因为很多代码都依赖它。 So, I would like to know, in C++, how would I convert a char* array to the byte buffer?所以,我想知道,在 C++ 中,如何将char*数组转换为字节缓冲区?

I have tried this:我试过这个:

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

When I print out the string that I convert, I get nothing, it is empty.当我打印出我转换的字符串时,我什么也没得到,它是空的。

Your C++ function implementation does not match the expectations of the C# function declaration.您的 C++ 函数实现与 C# 函数声明的预期不符。

The C# byte array is marshalled into the function as a pinned pointer to the array's raw memory. C# 字节数组作为指向数组原始内存的固定指针编组到函数中。 The syntax you are using in the C++ code for the parameter ( std::byte buf[256] ) is just syntax sugar, the compiler actually treats it as a pointer ( std::byte* buf ).您在 C++ 代码中使用的参数语法( std::byte buf[256] )只是语法糖,编译器实际上将其视为指针( std::byte* buf )。 Which is fine in this situation.在这种情况下这很好。 However, your C++ function is not actually copying anything into the memory that the pointer is pointing at.但是,您的 C++ 函数实际上并未将任何内容复制到指针指向的内存中。 You are simply changing the pointer itself to point at a different memory address.您只是将指针本身更改为指向不同的内存地址。 And the pointer itself is a local variable, so when the function exits, the pointer will no longer exist, and it won't matter what it is pointing at.而且指针本身是一个局部变量,所以当函数退出时,指针将不复存在,指向什么也无所谓。

Also, the C# declaration is expecting the function to return something that can be marshalled to a .NET string , but the C++ function is not actually return 'ing anything at all.此外,C# 声明期望函数返回可以编组为 .NET string的内容,但 C++ 函数实际上根本没有return任何内容。 The default marshalling behavior for a string return value is as UnmanagedType.LPStr , so the C++ function needs to return a pointer to a null-terminated char* string. string返回值的默认编组行为是UnmanagedType.LPStr ,因此 C++ 函数需要返回一个指向以 null 结尾的char*字符串的指针。 The memory for that string must be allocated with CoTaskMemAlloc() , as the marshaller will take ownership of the memory and free it with CoTaskMemFree() after converting the char data to a string .该字符串的内存必须使用CoTaskMemAlloc()分配,因为编组器将获取内存的所有权并在将char数据转换为string后使用CoTaskMemFree()释放它。

Also, the C++ function has no calling convention defined, so it is going to use the compiler's default (which is usually __cdecl , unless you change your compiler's settings).此外,C++ 函数没有定义调用约定,因此它将使用编译器的默认值(通常是__cdecl ,除非您更改编译器的设置)。 However, the default calling convention that .NET's DllImport expects the C++ function to use is __stdcall instead (for compatibility with Win32 APIs).但是,.NET 的DllImport期望 C++ 函数使用的默认调用约定是__stdcall (为了与 Win32 API 兼容)。 This mismatch won't matter in 64bit, but it matters alot in 32bit.这种不匹配在 64 位中无关紧要,但在 32 位中很重要。

Without changing your C# declaration, try this on the C++ side:在不更改 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;
}

That being said, it is weird to have a function that returns a string in both a byte array output parameter and in a return value.话虽如此,有一个函数在字节数组输出参数和返回值中都返回一个字符串是很奇怪的。 Are you sure the byte array is not meant to be used as an input parameter instead, where the function parses its content to extract amd a string?您确定字节数组不打算用作输入参数,而是函数解析其内容以提取字符串? That would make more sense.那会更有意义。 It would really help if you would update your question to show how your .NET code is actually calling the C++ function and using the byte array.如果您更新您的问题以显示您的 .NET 代码如何实际调用 C++ 函数并使用字节数组,这将非常有帮助。

When you write当你写

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

that declares buf as pointer to 256 bytes, not an array.buf声明为指向 256 字节的指针,而不是数组。 So when you later write所以当你以后写

buf = ptr;

all you are doing is changing the local variable buf to now point at ptr .您所做的只是将局部变量buf更改为现在指向ptr And at the end of the function the local variable dies.并且在函数结束时局部变量死亡。

Use std::array<std::byte, 256>& and copy the string contents into that.使用std::array<std::byte, 256>&并将字符串内容复制到其中。 Or even better return a freshly made array instead of an in/out parameter.或者甚至更好地返回一个新制作的数组而不是一个输入/输出参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM