jacksondunstan / UnityNativeScripting

Unity Scripting in C++
https://jacksondunstan.com/articles/3938
MIT License
1.34k stars 135 forks source link

Convert System::String to c char string or std::string #43

Closed kitsek closed 5 years ago

kitsek commented 5 years ago

Hi, I need to implement that feature to interact System.string with C++ string, any idea of that? Found no api to do that, don't wanna implement in C# side, but I reckon conversion in C++ side should be more efficient.

desc: //a System.String obj char *str = obj.c_str();

jacksondunstan commented 5 years ago

It's important to remember that the only contents of a C++ System::String are the int32_t Handle that references an object on the C# side. It therefore doesn't have the characters necessary to implement a function like std::string::c_str(). You'll therefore need to use a C# function to extract the characters.

kitsek commented 5 years ago

According to what u said in an issue, I did as follow:

std::string GetCString(System::String &str)
{
    int length = Game::Utils::Bridge::GetCStringLength(str);
    wchar_t* wbuf = new wchar_t[length+1];
    char* buf = new char[length+1];
    Game::Utils::Bridge::GetCString(str, wbuf);
    sprintf(buf,"%ls",wbuf);
    auto r = std::string(buf);
    delete [] wbuf;
    delete [] buf;
    return r;
}

first get length, then allocate wstring, then get string. which i think is a bad implementation, not neat and efficient.

OK, i understand what u said. is there any way faster to get a cstr? I think maybe u can implement it in the project so that others don't have to reinvent the wheel

jacksondunstan commented 5 years ago

is there any way faster to get a cstr?

I suppose it depends on the implementations of Game::Utils::Bridge::GetCStringLength and Game::Utils::Bridge::GetCString.

I think maybe u can implement it in the project so that others don't have to reinvent the wheel

Yes, that would be a nice addition. String and other built-in types like Object need a larger overhaul to flesh out their functionality and extensibility. Perhaps this could be part of that.

sekkit commented 5 years ago

Hi, I just implemented two more features for System::String int -> GetLength() const char * -> CString() image image

Also implement two bridge methods Plugin::StringGetLength Plugin::StringCStr, this is easily done. To ease the pain of interop with marshal calls, I also add cache to frequently used values so that access performance can be improved. The CONVERSION between managed basic types and C++ basic types can(shall) be applied for all. A bold suggestion: Converting C# basic types to C++ basic types and vice versa is the right thing to do. Anyway, if you wanna send C char string to C# side, this conversion just happens either by Marshaling or another, unavoidable.

jacksondunstan commented 5 years ago

Thanks for submitting these code examples. I'll keep them in mind during any overhaul of basic types like String.