Streamline and improve std::string typemaps

Avoid unnecessary heap allocations, just use temporary variables.

Actually update the string parameters passed by pointer/non-const
reference. This requires the pointers passed to actually be non-const,
so update the C-specific unit test runme to use a char buffer instead of
a literal string.

Also simplify the code copying the string contents to just use strdup()
(if there are ever any platforms where this POSIX functions is not
available, we could just define it ourselves once instead of using
strlen() + malloc() + memcpy() manually twice).
This commit is contained in:
Vadim Zeitlin 2021-12-05 03:05:30 +01:00
commit aacc930023
2 changed files with 49 additions and 38 deletions

View file

@ -6,7 +6,8 @@
int main() int main()
{ {
char *myComposedString = c_backend_cpp_natural_std_string_myStringAppend("World, ", "Hello!"); char buf[] = "World, ";
char *myComposedString = c_backend_cpp_natural_std_string_myStringAppend(buf, "Hello!");
assert(myComposedString); assert(myComposedString);
assert(strcmp(myComposedString, "World, Hello!") == 0); assert(strcmp(myComposedString, "World, Hello!") == 0);

View file

@ -2,6 +2,31 @@
#include <string> #include <string>
%} %}
%fragment("SwigStrInOut", "header") {
class SwigStrInOut {
std::string str_;
char* ptr_;
size_t len_;
public:
void init(char* ptr) {
ptr_ = ptr;
if (ptr_) {
str_ = ptr_;
len_ = str_.length();
}
}
std::string* str() { return &str_; }
~SwigStrInOut() {
if (ptr_) {
memcpy(ptr_, str_.c_str(), len_);
ptr_[len_] = '\0';
}
}
};
}
namespace std { namespace std {
// use "const string &" typemaps for wrapping member strings // use "const string &" typemaps for wrapping member strings
@ -9,49 +34,34 @@ namespace std {
class string; class string;
%typemap(ctype) string "char *" %typemap(ctype) string, const string & "const char *"
%typemap(ctype) string * "char *" %typemap(ctype) string * "char *"
%typemap(ctype) string & "char *" %typemap(ctype) string & "char *"
%typemap(ctype) const string & "char *"
%typemap(in) string { %typemap(in) string %{
if ($input) { if ($input)
$1.assign($input); $1 = $input;
} %}
else {
$1.resize(0);
}
}
%typemap(in) const string &, string *, string & { %typemap(in) const string & (std::string temp) %{
if ($input) { if ($input)
$1 = new std::string($input); temp = $input;
} $1 = &temp;
else { %}
$1 = new std::string();
$1->resize(0);
}
}
%typemap(freearg) const string &, string *, string & { %typemap(in, fragment="SwigStrInOut") string * (SwigStrInOut temp), string & (SwigStrInOut temp) %{
if ($1) temp.init($input);
delete $1; $1 = temp.str();
} %}
%typemap(out) string { // Note that we don't support strings with embedded NULs, as there is no way to
const char *str = cppresult.c_str(); // return their length to C code anyhow.
size_t len = strlen(str); %typemap(out) string %{
$result = (char *) malloc(len + 1); $result = strdup(cppresult.c_str());
memcpy($result, str, len); %}
$result[len] = '\0';
}
%typemap(out) const string &, string *, string & { %typemap(out) const string &, string *, string & %{
const char *str = cppresult->c_str(); $result = strdup(cppresult->c_str());
size_t len = strlen(str); %}
$result = (char *) malloc(len + 1);
memcpy($result, str, len);
$result[len] = '\0';
}
} }