Fix Length & string reverse order typemap.

And add it to missing languages: C#, Java, Lua, PHP.

Signed-off-by: Erez Geva <ErezGeva2@gmail.com>
This commit is contained in:
Erez Geva 2024-06-27 13:55:31 +02:00
parent 07ce064814
commit cb68446ece
29 changed files with 539 additions and 10 deletions

View File

@ -939,6 +939,23 @@ In the wrapper function, the passed string will be expanded to a pointer and len
The <tt>(char *STRING, int LENGTH)</tt> multi-argument typemap is also available in addition to <tt>(char *STRING, size_t LENGTH)</tt>.
</p>
<p>
We also support passing parameters in reverse order
</p>
<div class="code">
<pre>
%apply (size_t LENGTH, char *STRING) { (size_t len, char *str) };
...
size_t parity(size_t len, char *str, size_t initial);
</pre>
</div>
<p>
The usage from target language will be identical.
In the wrapper function, the passed string will be expanded to a length parameter and pointer.
</p>
<H3><a name="Library_nn11">12.3.3 Using %newobject to release memory</a></H3>

View File

@ -0,0 +1,19 @@
/*
* A test case for reverse length string typemap
*/
%module char_binary_rev_len
#if !defined(SWIGC)
/* There is no concept of a higher level binary string in C */
%apply (size_t LENGTH, const char *STRING) { (size_t len, const char *str, ) }
#endif
%inline %{
struct Test {
size_t strlen(size_t len, const char *str) {
return len;
}
};
%}

View File

@ -146,6 +146,7 @@ CPP_TEST_CASES += \
cast_operator \
casts \
char_binary \
char_binary_rev_len \
char_strings \
chartest \
class_case \
@ -194,6 +195,7 @@ CPP_TEST_CASES += \
director_alternating \
director_basic \
director_binary_string \
director_binary_string_rev_len \
director_classes \
director_classic \
director_constructor \

View File

@ -0,0 +1,16 @@
using System;
using char_binary_rev_lenNamespace;
public class char_binary_rev_len_runme {
public static void Main() {
Test t = new Test();
string hile = "hile";
string hil0 = "hil\0";
if (t.strlen(hile) != 4)
throw new Exception("bad multi-arg typemap");
if (t.strlen(hil0) != 4)
throw new Exception("bad multi-arg typemap");
}
}

View File

@ -0,0 +1,28 @@
using System;
using director_binary_string_rev_lenNamespace;
public class director_binary_string_rev_len_runme
{
static void Main()
{
Caller caller = new Caller(new DirectorReverseLengthStringCallback());
int sum = caller.call();
if (sum != 9*2*8)
throw new Exception("Unexpected sum: " + sum);
}
}
public class DirectorReverseLengthStringCallback : Callback {
public DirectorReverseLengthStringCallback() : base() {}
public override int run(string dataBufferAA)
{
int ret = 0;
if (dataBufferAA != null) {
for (int i = 0; i < dataBufferAA.Length; i++)
ret += (int)dataBufferAA[i] * 2;
}
return ret;
}
}

View File

@ -0,0 +1,38 @@
%module(directors="1") director_binary_string_rev_len;
%feature("director") Callback;
#if !defined(SWIGC)
/* There is no concept of a higher level binary string in C */
%apply (size_t LENGTH, char *STRING) { (int sizeAA, char *dataBufferAA) };
#endif
%inline %{
#include <string.h>
#define BUFFER_SIZE_AA 8
class Callback {
public:
virtual ~Callback() {}
virtual int run(int sizeAA, char* dataBufferAA) {
return 0;
}
};
class Caller {
private:
Callback *_callback;
public:
Caller(Callback *cb): _callback(cb) {}
int call() {
if (_callback) {
char aa[BUFFER_SIZE_AA];
memset(aa, 9, BUFFER_SIZE_AA);
return _callback->run(BUFFER_SIZE_AA, aa);
}
return 0;
}
};
%}

View File

@ -19,6 +19,10 @@ top_builddir = @top_builddir@
GUILE = @GUILE@
GUILE_RUNTIME=
FAILING_CPP_TESTS = \
char_binary_rev_len \
director_binary_string_rev_len \
C_TEST_CASES = long_long \
list_vector \
multivalue \

View File

@ -0,0 +1,25 @@
import char_binary_rev_len.*;
public class char_binary_rev_len_runme {
static {
try {
System.loadLibrary("char_binary_rev_len");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[]) {
Test t = new Test();
String hile = "hile";
if (t.strlen(hile) != 4)
throw new RuntimeException("bad multi-arg typemap");
String hil0 = "hil\0";
if (t.strlen(hil0) != 4)
throw new RuntimeException("bad multi-arg typemap");
}
}

View File

@ -0,0 +1,41 @@
import director_binary_string_rev_len.*;
public class director_binary_string_rev_len_runme {
static {
try {
System.loadLibrary("director_binary_string_rev_len");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
System.exit(1);
}
}
public static void main(String argv[]) {
Callback callback = new DirectorReverseLengthStringCallback();
Caller caller = new Caller(callback);
int sum = caller.call();
if (sum != 9*2*8)
throw new RuntimeException("Unexpected sum: " + sum);
}
}
class DirectorReverseLengthStringCallback extends Callback {
public DirectorReverseLengthStringCallback() {
super();
}
@Override
public int run(String dataBufferAA)
{
int ret = 0;
if (dataBufferAA != null) {
for (int i = 0; i < dataBufferAA.length(); i++)
ret += (int)dataBufferAA.charAt(i) * 2;
}
return ret;
}
}

View File

@ -0,0 +1,9 @@
var char_binary_rev_len = require("char_binary_rev_len");
var t = new char_binary_rev_len.Test();
if (t.strlen('hile') != 4) {
throw("bad multi-arg typemap 1");
}
if (t.strlen('hil\0') != 4) {
throw("bad multi-arg typemap 2");
}

View File

@ -0,0 +1,12 @@
require("import") -- the import fn
import("char_binary_rev_len") -- import lib
v = char_binary_rev_len
-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})
t = v.Test()
assert(t:strlen("hile") == 4, "bad multi-arg typemap");
assert(t:strlen("hil\0") == 4, "bad multi-arg typemap");

View File

@ -20,12 +20,14 @@ top_builddir = @top_builddir@
FAILING_CPP_TESTS = \
allprotected \
apply_strings \
char_binary_rev_len \
cpp11_decltype \
cpp11_director_enums \
cpp11_strongly_typed_enumerations \
cpp_enum \
default_constructor \
director_binary_string \
director_binary_string_rev_len \
director_comparison_operators \
director_enum \
director_primitives \

View File

@ -0,0 +1,12 @@
char_binary_rev_len
t = char_binary_rev_len.Test();
str = "hile";
if (t.strlen(str) != 4)
disp(t.strlen(str));
error("bad multi-arg typemap");
endif
if (t.strlen("hil\000") != 4)
error("bad multi-arg typemap");
endif

View File

@ -0,0 +1,21 @@
director_binary_string_rev_len
function self=DirectorReverseLengthStringCallback()
global director_binary_string_rev_len;
self=subclass(director_binary_string_rev_len.Callback());
self.run=@DirectorReverseLengthStringCallback_run;
end
function ret=DirectorReverseLengthStringCallback_run(self, dataBufferAA)
ret = 0;
for i = 1:length(dataBufferAA)
ret = ret + double(dataBufferAA(i)) * 2;
end
end
callback = DirectorReverseLengthStringCallback();
caller = director_binary_string_rev_len.Caller(callback);
sum = caller.call();
if (sum != 9*2*8)
error(sum);
end

View File

@ -0,0 +1,11 @@
use strict;
use warnings;
use Test::More tests => 4;
BEGIN { use_ok('char_binary_rev_len') }
require_ok('char_binary_rev_len');
my $t = char_binary_rev_len::Test->new();
is($t->strlen('hile'), 4, "string typemap");
is($t->strlen("hil\0"), 4, "string typemap");

View File

@ -0,0 +1,27 @@
use strict;
use warnings;
use Test::More tests => 3;
BEGIN { use_ok 'director_binary_string_rev_len' }
require_ok 'director_binary_string_rev_len';
{
package DirectorReverseLengthStringCallback;
use base 'director_binary_string_rev_len::Callback';
sub run {
my $ret = 0;
my ($self, $dataBufferAA) = @_;
if(defined $dataBufferAA) {
$ret += ord($_) * 2 for(split('', $dataBufferAA));
}
return $ret;
}
}
{
print "Start\n";
my $callback = DirectorReverseLengthStringCallback->new();
my $caller = director_binary_string_rev_len::Caller->new($callback);
my $sum = $caller->call();
is($sum, 9*2*8, 'Unexpected sum: ' . $sum);
}

View File

@ -0,0 +1,14 @@
<?php
require "tests.php";
check::functions(array());
check::classes(array('Test'));
$t = new Test();
$str = 'hile';
check::equal(4, $t->strlen($str), "bad multi-arg typemap");
check::equal(4, $t->strlen("hil\000"), "bad multi-arg typemap");
check::done();

View File

@ -0,0 +1,27 @@
<?php
require "tests.php";
// No new functions
check::functions(array());
check::classes(array('director_binary_string_rev_len','Callback','Caller'));
// No new vars
check::globals(array());
class DirectorBinaryStringCallback extends Callback {
function run(string $dataBufferAA)
{
$ret = 0;
if ($dataBufferAA != null) {
for ($i = 0; $i < strlen($dataBufferAA); $i++)
$ret = $ret + ord($dataBufferAA[$i]) * 2;
}
return $ret;
}
}
$callback = new DirectorBinaryStringCallback();
$caller = new Caller($callback);
$sum = $caller->call();
check::equal($sum, 9*2*8, "Unexpected sum: $sum");

View File

@ -0,0 +1,8 @@
from char_binary_rev_len import *
t = Test()
if t.strlen("hile") != 4:
raise RuntimeError("bad multi-arg typemap {}".format(t.strlen("hile")))
if t.strlen("hil\0") != 4:
raise RuntimeError("bad multi-arg typemap")

View File

@ -0,0 +1,16 @@
import director_binary_string_rev_len
class DirectorBinaryStringCallback(director_binary_string_rev_len.Callback):
def run(self, dataBufferAA):
ret = 0
for c in dataBufferAA:
ret += ord(c) * 2
return ret
callback = DirectorBinaryStringCallback()
caller = director_binary_string_rev_len.Caller(callback)
sum = caller.call()
if sum != 9*2*8:
raise RuntimeError("Unexpected sum: {}".format(sum))

View File

@ -0,0 +1,14 @@
#!/usr/bin/env ruby
#
# Put description here
#
require 'swig_assert'
require 'char_binary_rev_len'
include Char_binary_rev_len
t = Test.new
str = 'hile'
swig_assert(t.strlen(str) == 4, binding, 'bad multi-arg typemap')
swig_assert(t.strlen("hil\000") == 4, binding, 'bad multi-arg typemap')

View File

@ -0,0 +1,25 @@
#!/usr/bin/env ruby
#
# Put description here
#
require 'swig_assert'
require 'director_binary_string_rev_len'
class DirectorBinaryStringCallback < Director_binary_string_rev_len::Callback
def run(dataBufferAA)
ret = 0
unless dataBufferAA.nil?
dataBufferAA.each_char do |c|
ret += c.ord * 2
end
end
return ret
end
end
caller = Director_binary_string_rev_len::Caller.new(DirectorBinaryStringCallback.new)
sum = caller.call()
raise RuntimeError if sum != 9*2*8

View File

@ -0,0 +1,10 @@
exec("swigtest.start", -1);
t = new_Test();
str = "hile";
if Test_strlen(t, str) <> 4 then
swigtesterror("bad multi-arg typemap");
end
// String can not contain null character same as C
exec("swigtest.quit", -1);

View File

@ -0,0 +1,20 @@
if [ catch { load ./char_binary_rev_len[info sharedlibextension] Char_binary_rev_len} err_msg ] {
puts stderr "Could not load shared object:\n$err_msg"
}
Test t
set str "hile"
if { [ t strlen $str ] != 4 } {
puts stderr "bad multi-arg typemap"
exit 1
}
# The Escape Sequence of zero is translated to 2 UTF-8 bytes,
# as done in Modified UTF-8.
# Standard UTF-8 repreasent zero as a single byte with value zero.
set str2 "hi\u0000"
if { [ t strlen $str2 ] != 4 } {
puts stderr "bad multi-arg typemap"
exit 1
}

View File

@ -1135,7 +1135,7 @@ SWIGEXPORT char *SWIGSTDCALL SWIG_csharp_string_str(SWIG_csharp_string *p) {
#endif
%}
/* string & length typemap */
/* String & length typemap */
%typemap(cstype) (const char *STRING, size_t LENGTH) "string"
%typemap(ctype) (const char *STRING, size_t LENGTH) "void *"
@ -1177,6 +1177,49 @@ SWIGEXPORT char *SWIGSTDCALL SWIG_csharp_string_str(SWIG_csharp_string *p) {
%apply (const char *STRING, size_t LENGTH) { (const char *STRING, int LENGTH) }
%apply (char *STRING, size_t LENGTH) { (char *STRING, int LENGTH) }
/* Length & string reverse order typemap */
%typemap(cstype) (size_t LENGTH, const char *STRING) "string"
%typemap(ctype) (size_t LENGTH, const char *STRING) "void *"
%typemap(imtype) (size_t LENGTH, const char *STRING) "global::System.IntPtr"
%typemap(csin) (size_t LENGTH, const char *STRING) "$modulePINVOKE.SWIGStringWithLengthHelper.SWIG_csharp_string_to_c($csinput)"
%typemap(in, canthrow=1, fragment="SWIG_csharp_string") (size_t LENGTH, const char *STRING) {
SWIG_csharp_string *p;
p = (SWIG_csharp_string *)$input;
if (p) {
$2 = ($2_ltype)p->str;
$1 = ($1_ltype)p->size; /* We use number of bytes */
} else {
$1 = 0;
$2 = 0;
}
}
%typemap(freearg, fragment="SWIG_csharp_string") (size_t LENGTH, const char *STRING) %{
{
SWIG_csharp_string *p;
p = (SWIG_csharp_string *)$input;
if (p) {
free(p->str);
free(p);
}
}
%}
%typemap(directorin) (size_t LENGTH, const char *STRING) %{
if ($2 && $1 > 0) {
$input = malloc(sizeof(SWIG_csharp_string));
if ($input) {
SWIG_csharp_string *p = (SWIG_csharp_string *)$input;
p->str = (char *)$2;
p->size = (int)$1;
}
}
%}
%typemap(csdirectorin) (size_t LENGTH, const char *STRING) "$modulePINVOKE.SWIGStringWithLengthHelper.SWIG_c_to_csharp_string($iminput)"
%apply (size_t LENGTH, const char *STRING) { (size_t LENGTH, char *STRING) }
%apply (size_t LENGTH, const char *STRING) { (int LENGTH, const char *STRING) }
%apply (size_t LENGTH, char *STRING) { (int LENGTH, char *STRING) }
/* csharp keywords */
%include <csharpkw.swg>

View File

@ -1458,6 +1458,44 @@ SWIG_PROXY_CONSTRUCTOR(true, true, SWIGTYPE)
{ if ($input && $1) JCALL4(GetByteArrayRegion, jenv, $input, 0, (jsize)$2, (jbyte *)$1); }
%apply (char *STRING, size_t LENGTH) { (char *STRING, int LENGTH) }
/* Length & string reverse order typemap */
%typemap(jni) (size_t LENGTH, const char *STRING) "jbyteArray"
%typemap(jtype) (size_t LENGTH, const char *STRING) "byte[]"
%typemap(jstype) (size_t LENGTH, const char *STRING) "String"
%typemap(javain) (size_t LENGTH, const char *STRING) %{($javainput == null) ? null : $javainput.getBytes()%}
%typemap(freearg) (size_t LENGTH, const char *STRING) ""
%typemap(in) (size_t LENGTH, const char *STRING) {
if ($input) {
$2 = ($2_ltype) JCALL2(GetByteArrayElements, jenv, $input, 0);
$1 = ($1_type) JCALL1(GetArrayLength, jenv, $input);
} else {
$1 = 0;
$2 = 0;
}
}
%typemap(argout) (size_t LENGTH, const char *STRING) {
if ($input) JCALL3(ReleaseByteArrayElements, jenv, $input, (jbyte *)$2, JNI_ABORT);
}
%typemap(directorin, descriptor="Ljava/lang/String;", noblock=1) (size_t LENGTH, const char *STRING) {
$input = 0;
if ($2) {
$input = JCALL1(NewByteArray, jenv, (jsize)$1);
if (!$input) return $null;
JCALL4(SetByteArrayRegion, jenv, $input, 0, (jsize)$1, (jbyte *)$2);
}
Swig::LocalRefGuard $2_refguard(jenv, $input);
}
%typemap(javadirectorin, descriptor="[B") (size_t LENGTH, const char *STRING) "($jniinput == null) ? null : new String($jniinput)"
%apply (size_t LENGTH, const char *STRING) { (size_t LENGTH, char *STRING) }
/* Enable write-back for non-const version */
%typemap(argout) (size_t LENGTH, char *STRING) {
if ($input) JCALL3(ReleaseByteArrayElements, jenv, $input, (jbyte *)$2, 0);
}
%typemap(directorargout, noblock=1) (size_t LENGTH, char *STRING)
{ if ($input && $2) JCALL4(GetByteArrayRegion, jenv, $input, 0, (jsize)$1, (jbyte *)$2); }
%apply (size_t LENGTH, char *STRING) { (int LENGTH, char *STRING) }
/* java keywords */
%include <javakw.swg>

View File

@ -64,6 +64,18 @@
%apply (const char *STRING, size_t LENGTH) { (const char *STRING, int LENGTH) }
%apply (char *STRING, size_t LENGTH) { (char *STRING, int LENGTH) }
/* Length & string reverse order typemap */
%typemap(in,checkfn="lua_isstring") (size_t LENGTH, const char *STRING) {
size_t len;
$2 = ($2_ltype)lua_tolstring(L, $input, &len);
SWIG_contract_assert($2, "non null string");
$1 = ($1_ltype)len;
}
%apply (size_t LENGTH, const char *STRING) { (size_t LENGTH, char *STRING) }
%apply (size_t LENGTH, const char *STRING) { (int LENGTH, const char *STRING) }
%apply (size_t LENGTH, char *STRING) { (int LENGTH, char *STRING) }
/* -----------------------------------------------------------------------------
* Overloaded operator support
* ----------------------------------------------------------------------------- */

View File

@ -101,6 +101,24 @@
%apply (const char *STRING, size_t LENGTH) { (char *STRING, size_t LENGTH) }
%apply (char *STRING, size_t LENGTH) { (char *STRING, int LENGTH) }
/* Length & string reverse order typemap */
%typemap(in, phptype="string", noblock=1) (size_t LENGTH, const char *STRING) %{
convert_to_string(&$input);
$2 = ($2_ltype) Z_STRVAL($input);
$1 = ($1_ltype) Z_STRLEN($input);
%}
%typemap(directorin, noblock=1) (size_t LENGTH, const char *STRING) {
if (!$2) {
ZVAL_EMPTY_STRING($input);
} else {
ZVAL_STRINGL($input, (const char*)$2, (size_t)$1);
}
}
%apply (size_t LENGTH, const char *STRING) { (int LENGTH, const char *STRING) }
%apply (size_t LENGTH, const char *STRING) { (size_t LENGTH, char *STRING) }
%apply (size_t LENGTH, char *STRING) { (int LENGTH, char *STRING) }
/* Object passed by value. Convert to a pointer */
%typemap(in, phptype="SWIGTYPE") SWIGTYPE ($&1_ltype tmp)
%{

View File

@ -449,7 +449,7 @@
/* reverse order typemap */
%typemap(in,noblock=1,fragment=#SWIG_AsCharPtrAndSize)
(size_t LENGTH, Char *STRING) (int res, Char *buf = 0, size_t size = 0, int alloc = 0)
(size_t LENGTH, const Char *STRING) (int res, Char *buf = 0, size_t size = 0, int alloc = 0)
{
res = SWIG_AsCharPtrAndSize($input, &buf, &size, &alloc);
if (!SWIG_IsOK(res)) {
@ -458,11 +458,11 @@
$2 = %reinterpret_cast(buf, $2_ltype);
$1 = %numeric_cast(size - 1, $1_ltype);
}
%typemap(freearg,noblock=1,match="in") (size_t LENGTH, Char *STRING) {
%typemap(freearg,noblock=1,match="in") (size_t LENGTH, const Char *STRING) {
if (alloc$argnum == SWIG_NEWOBJ) SWIG_DeleteCharArray(buf$argnum);
}
%typemap(directorin,noblock=1,fragment=#SWIG_FromCharPtrAndSize)
(size_t LENGTH, Char *STRING)
(size_t LENGTH, const Char *STRING)
{
if ($2 && $1 > 0) {
$input = SWIG_FromCharPtrAndSize((const char*)$2, (size_t)$1);
@ -471,17 +471,17 @@
}
}
%typemap(in) (size_t LENGTH, const Char *STRING) = (Char *STRING, size_t LENGTH);
%typemap(freearg) (size_t LENGTH, const Char *STRING) = (Char *STRING, size_t LENGTH);
%typemap(directorin) (size_t LENGTH, const Char *STRING) = (Char *STRING, size_t LENGTH);
%typemap(in) (size_t LENGTH, Char *STRING) = (size_t LENGTH, const Char *STRING);
%typemap(freearg) (size_t LENGTH, Char *STRING) = (size_t LENGTH, const Char *STRING);
%typemap(directorin) (size_t LENGTH, Char *STRING) = (size_t LENGTH, const Char *STRING);
/* old 'int' form */
%typemap(in) (int LENGTH, const Char *STRING) = (size_t LENGTH, const Char *STRING);
%typemap(freearg) (int LENGTH, const Char *STRING) = (size_t LENGTH, const Char *STRING);
%typemap(directorin) (int LENGTH, const Char *STRING) = (size_t LENGTH, const Char *STRING);
%typemap(in) (int LENGTH, Char *STRING) = (size_t LENGTH, Char *STRING);
%typemap(freearg) (int LENGTH, Char *STRING) = (size_t LENGTH, Char *STRING);
%typemap(directorin) (int LENGTH, Char *STRING) = (size_t LENGTH, Char *STRING);
%typemap(in) (int LENGTH, const Char *STRING) = (size_t LENGTH, Char *STRING);
%typemap(freearg) (int LENGTH, const Char *STRING) = (size_t LENGTH, Char *STRING);
%typemap(directorin) (int LENGTH, const Char *STRING) = (size_t LENGTH, Char *STRING);
%enddef