[GDNative] Convert godot string to const char *

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By quendera
:warning: Old Version Published before Godot 3 was released.

Hi,
I’m working on a GDNative project to incorporate MySQL in godot.

Godot outputs strings as godot_string and my C function requires the string to be a const char *.

How do I convert godot_string to a const char * ?
It’s close to functional but I seem to be missing the simplest thing…

My Godot code:

func _ready():
var gdn = GDNative.new()
gdn.library = load("res://lib/sqllib.tres")

gdn.initialize()
gdn.call_native("standard_varcall", "query", [])

gdn.terminate()

My C code:

void GDN_EXPORT sendstring(godot_string query) {

   MYSQL *m = mysql_init(NULL);
   mysql_real_connect(m, "my", "server", "details", "here", 0, NULL, 0);
   mysql_real_query(m, query, strlen(query));
   mysql_close(m); }
:bust_in_silhouette: Reply From: Karroffel

Hey!

Okay a few things:

  • GDNative.call_native() uses a “calling convention” (more on that down below), the name of the function to call and an array of arguments.

  • the calling convention is "standard_varcall", that means, that the function that’s being called has to return a godot_variant and the arguments have to be void *data (unused for now) and godot_array *args which contains the arguments.

  • the name is the name of the function in the library, so in your case it’s sendstring.

Taking those things into account, the call has to be gdn.call_native("standard_varcall", "sendstring", ["query"]).

You can get the elements of the array by using the godot_array_* functions.

An godot_array contains godot_variants, you can get a string from that with godot_variant_as_string. When you have a godot_string you can use godot_string_get_data.

As you can see, it’s a few calls to unwrap the data from that uniform representation. But that’s just how it goes if you want to be as flexible as possible. Language bindings can make those conversions easier, so stay tuned for that in future.

To be a bit more specific, using the function godot_string_get_data defined here, I’m imagining this would give the desired const char * (if query is a godot_string):

const char *c_query;
int *c_query_length;
godot_string_get_data(&query, c_query, c_query_length);

Or maybe the simpler:

const char *c_query = godot_string_c_str(&query);

would also work.

In all those function definitions in the page I’m linking however I’m not too sure what GDAPI means.

piever | 2017-10-03 08:57

@piever

The GDAPI is for attribute that might be needed on different platforms, so it’s not really important for the user. Many libraries have different “API” macros.

And yes, I forgot that there is the godot_string_c_str() function, good catch!

Karroffel | 2017-10-03 12:18

@Karroffel I have an additional question: I’ve seen that godot_string_get_data returns an int as size (whereas the standard strlen in C returns unsigned long). So I wanted to ask if there is good support for very long strings. Is there risk of losing data when converting a string of more than 2^16 characters? Does godot_string have a maximum length?

piever | 2017-10-04 11:19

int usually is 32 bits, so 2¹⁶ should not be a problem at all.

Godot’s Vector class only allows for at most 2³² elements, so it’s a limit set by Godot.

Karroffel | 2017-10-04 11:29

Hi @Karoffel,

Thank you very much for the constant help in the Godot community and in the development of GDNative. I posted an issue following up on this that you may have some input on.
Calling a GDNative C function with too many functions in it crashes debugger · Issue #11967 · godotengine/godot · GitHub

quendera | 2017-10-09 13:53

I solved this by doing:

String godotstr("something");
std::wstring ws = godotstr.c_str();
std::string s( ws.begin(), ws.end() );
char* c = s.c_str();

I had to do this because std::cout do not accept std::wstring.

Godot String.c_str() is returning a CharType*, and

typedef wchar_t CharType;

Using built-in methods should be much more efficient, just in case it might ever helps someone.

frankiezafe | 2018-03-21 18:58

In godot 4.1 this works to get a char* pointer from which a std:string can be created:

#define godot2stdstr(s) (const char *)(s).to_utf8_buffer().ptr()

limor | 2023-06-21 07:56