String support/improvements
JmgrArt opened this issue · comments
Hi. I saw in the project's readme that the generator does not support string
yet. I have however added an abstract method taking a string parameter to the AbstractBaseBallScript
class and have implemented it on the C++ side. All I missed was some way to get a const char *
from a String
, so I added a c_str()
method to it, adding binding methods similar to Plugin::StringNew
. This seem to work, and I managed to transfer a C# string from Unity to the C++ side. I am wondering however if I did the right thing and if this could break in some ways. What do you think?
By the way, would it be possible to add conversion from/to std::string to the String class? If you don't want to force people to use the C++ Standard Library you could add some CMake configuration option like USE_STL.
Hi @JmgrArt, the string
class has been supported since the very beginning of the project. The README.md just says that string
methods aren't supported. This is because the string
type is hard-coded as opposed to being generated by the code generator. So there's currently no way to expose more functionality of the string
type such as the Substring
method. Some day I'd like to address this, but don't have a solid plan at the moment, just a vague hope that the code generator will become robust enough that string
no longer needs to be hard-coded at all.
As for your question about getting the character contents of a string
, there's no way to do this right now. That said, it'd be rather easy to create a function like this to copy out the characters to a C++ buffer. Here's one idea for the C# function:
public static class StringContents
{
public static void GetChars(
string str,
IntPtr into,
int index = 0,
int len = -1)
{
int i = index;
int off = index + index;
int end = index + (len >= 0 ? len : str.Length);
while (i < end)
{
Marshal.WriteInt16(into, off, str[i]);
i++;
off += 2;
}
}
}
Then you'd call this from C++ like this:
int16_t buf[1024];
System::String str("Hello, world!");
StringContents::GetChars(str, &buf);
The usual binding layer would apply here, but it can't currently handle this because there's no support yet for pointers or IntPtr
in the project. Eventually there will be, and you'll be able to write and expose functions like this with the code generator. For now, I'd need to hard-code that like with the other parts of string
, which I'd like to avoid since it'll hopefully all be replaced at some point when a more general solution for string
is implemented.
As for std::string
, it should be trivial to convert one to a C# string
:
std::string cppStr("Hello, world!");
System::String csharpStr(cppStr.c_str());
As mentioned above, there's no way to perform the reverse of this point.
The same strategy of converting to a "C string" works for plenty of other C++ string types out there like std::string_view, std::wstring, QString, gstring, FbString, CString, and CsString. I think it's best that this project avoid adding support for all the various string types, many of which have surprisingly compelling arguments to adopt them, and instead simply support a pass-through pointer like const char*
or const int16_t*
to reduce complexity like additional CMake configuration and library dependencies.
Regarding your own implementation and whether you did "the right thing," I can't say for sure since I haven't seen it. As long as you're making a copy of the characters into a buffer provided by C++, it seems like you'll be fine.