Sort out directorout typemaps for std::string_view

With Perl the returned string is still being corrupted (the testcase
flags this as "TODO" for Perl's test harness).

Warnings aren't currently emitted for Perl, Ruby or Tcl as I'm not
seeing where in the UTL maze the directorout typemap actually gets
defined.
This commit is contained in:
Olly Betts 2023-12-21 10:35:14 +13:00
parent 18afec7860
commit ccf4f6ec72
9 changed files with 58 additions and 16 deletions

View File

@ -22,6 +22,9 @@ public class runme
cpp17_director_string_view_B b = new cpp17_director_string_view_B("hello");
s = b.get_first();
if (s != "cpp17_director_string_view_B.get_first") throw new Exception("get_first() failed");
s = b.call_get_first();
if (s != "cpp17_director_string_view_B.get_first") throw new Exception("call_get_first() failed");

View File

@ -24,6 +24,9 @@ public class cpp17_director_string_view_runme {
cpp17_director_string_view_B b = new cpp17_director_string_view_B("hello");
s = b.get_first();
if (!s.equals("cpp17_director_string_view_B.get_first")) throw new RuntimeException("get_first() failed");
s = b.call_get_first();
if (!s.equals("cpp17_director_string_view_B.get_first")) throw new RuntimeException("call_get_first() failed");

View File

@ -1,6 +1,6 @@
use strict;
use warnings;
use Test::More tests => 5;
use Test::More tests => 7;
BEGIN { use_ok 'cpp17_director_string_view' }
require_ok 'cpp17_director_string_view';
@ -11,8 +11,11 @@ require_ok 'cpp17_director_string_view';
sub get_first { my($self) = @_;
die "SUPER RESOLVE BAD" if $in_first;
local $in_first = 1;
# Since std::string_view contains a pointer into a string, the string
# cannot be a temporary in order to avoid undefined behaviour.
my $x = $self->SUPER::get_first();
return $x . " world!";
$self->{cached_string} = $x . " world!";
return $self->{cached_string};
}
our $in_process_text = 0;
sub process_text { my($self, $string) = @_;
@ -26,10 +29,12 @@ require_ok 'cpp17_director_string_view';
my $b = B->new("hello");
isa_ok $b, 'B';
$b->get(0);
is $b->get(0), "hello";
{ local $TODO = "Return value gets corrupted";
is $b->get_first(), "hello world!"; }
is $b->get_first(), "hello world!";
is $b->call_get_first(), "hello world!";
}
$b->call_process_func();

View File

@ -12,8 +12,13 @@ check::globals(array());
class B extends A {
public $smem;
private $cached_string;
function get_first() {
return parent::get_first() . " world!";
// Since std::string_view contains a pointer into a string, the string
// cannot be a temporary in order to avoid undefined behaviour.
$this->cached_string = parent::get_first() . " world!";
return $this->cached_string;
}
function process_text($string) {
@ -24,8 +29,11 @@ class B extends A {
$b = new B("hello");
$b->get(0);
check::equal($b->get_first(),"hello world!", "get_first failed");
check::equal($b->get(0), "hello", "get(0) failed");
check::equal($b->get_first(), "hello world!", "get_first failed");
check::equal($b->call_get_first(), "hello world!", "call_get_first failed");
$b->call_process_func();

View File

@ -7,8 +7,8 @@ class B(A):
A.__init__(self, string)
def get_first(self):
# Given std::string_view is just a pointer into a string, the string
# cannot be a temporary in order to avoid undefined behaviour
# Since std::string_view contains a pointer into a string, the string
# cannot be a temporary in order to avoid undefined behaviour.
self.cached_string = A.get_first(self) + " world!"
return self.cached_string
@ -19,7 +19,9 @@ class B(A):
b = B("hello")
b.get(0)
if b.get(0) != "hello":
raise RuntimeError("b.get(0): {}".format(b.get(0)))
if b.get_first() != "hello world!":
raise RuntimeError("b.get_first(): {}".format(b.get_first()))

View File

@ -12,13 +12,31 @@ require 'swig_assert'
require 'cpp17_director_string_view'
class B < Cpp17_director_string_view::A
attr_accessor :smem
def initialize(some_string)
super(some_string)
end
def get_first()
# Since std::string_view contains a pointer into a string, the string
# cannot be a temporary in order to avoid undefined behaviour.
@cached_string = super() + " world!"
return @cached_string
end
def process_text(string)
super(string)
@smem = "hello"
end
end
b = B.new("hello")
b.get_first
b.get(0)
raise RuntimeError if b.get(0) != "hello"
raise RuntimeError if b.get_first() != "hello world!"
raise RuntimeError if b.call_get_first() != "hello world!"
b.call_process_func()
raise RuntimeError if b.smem != "hello"

View File

@ -36,12 +36,15 @@ class string_view;
$1 = std::string_view($input); %}
%typemap(out) string_view %{ $result = SWIG_csharp_string_callback(std::string($1).c_str()); %}
%typemap(directorout, canthrow=1) string_view
%typemap(directorout, canthrow=1, warning=SWIGWARN_TYPEMAP_THREAD_UNSAFE_MSG) string_view
%{ if (!$input) {
SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "null string", 0);
return $null;
}
$result = std::string_view($input); %}
/* possible thread/reentrant code problem */
static std::string $1_str;
$1_str = $input;
$result = std::string_view($1_str); %}
%typemap(directorin) string_view %{ $input = std::string($1).c_str(); %}

View File

@ -113,7 +113,7 @@ class string_view;
$1_str = $1_pstr;
static $*1_ltype $1_strview;
$1_strview = $1_str;
$result = &$1_str;
$result = &$1_strview;
jenv->ReleaseStringUTFChars($input, $1_pstr); %}
%typemap(directorin,descriptor="Ljava/lang/String;") const string_view &

View File

@ -31,7 +31,7 @@ namespace std {
$1 = &temp;
%}
%typemap(directorout) string_view %{
%typemap(directorout, warning=SWIGWARN_TYPEMAP_DIRECTOROUT_PTR_MSG) string_view %{
convert_to_string($input);
$result = std::string_view(Z_STRVAL_P($input), Z_STRLEN_P($input));
%}