diff --git a/CHANGES.current b/CHANGES.current
index 2aa1e8d7b..20524df69 100644
--- a/CHANGES.current
+++ b/CHANGES.current
@@ -5,6 +5,11 @@ See the RELEASENOTES file for a summary of changes in each release.
Version 2.0.2 (in progress)
===========================
+2010-01-14: wsfulton
+ Added some missing multi-argument typemaps: (char *STRING, size_t LENGTH) and
+ (char *STRING, int LENGTH). Documentation for this updated. Java patch from
+ Volker Grabsch.
+
2010-12-30: klickverbot
[C#, D, Java] Check for collision of parameter names with target
language keywords when generating the director glue code.
diff --git a/Doc/Manual/Java.html b/Doc/Manual/Java.html
index ef5604a05..c6ef2b425 100644
--- a/Doc/Manual/Java.html
+++ b/Doc/Manual/Java.html
@@ -4401,6 +4401,49 @@ well suited for applications in which you need to create buffers,
package binary data, etc.
+Binary data vs Strings
+
+
+By default SWIG handles char * as a string but there is a handy multi-argument typemap available as mentioned in Passing binary data.
+The following simple example demonstrates using a byte array instead of passing the default string type and length to the wrapped function.
+
+
+
+
+
+%apply (char *STRING, size_t LENGTH) { (const char data[], size_t len) }
+%inline %{
+void binaryChar1(const char data[], size_t len) {
+ printf("len: %d data: ", len);
+ for (size_t i=0; i<len; ++i)
+ printf("%x ", data[i]);
+ printf("\n");
+}
+%}
+
+
+
+
+Calling from Java requires just the byte array to be passed in as the multi-argument typemap being applied reduces the number of arguments in the target language to one, from the original two:
+
+
+
+
+byte[] data = "hi\0jk".getBytes();
+example.binaryChar1(data);
+
+
+
+
+resulting in the output
+
+
+
+$ java runme
+len: 5 data: 68 69 0 6a 6b
+
+
+
23.8.5 Overriding new and delete to allocate from Java heap
diff --git a/Doc/Manual/Library.html b/Doc/Manual/Library.html
index 1f465dab5..31f8c47b7 100644
--- a/Doc/Manual/Library.html
+++ b/Doc/Manual/Library.html
@@ -824,20 +824,20 @@ If you have a function that expects binary data,
-int parity(char *str, int len, int initial);
+size_t parity(char *str, size_t len, size_t initial);
-you can wrap the parameters (char *str, int len) as a single
+you can wrap the parameters (char *str, size_t len) as a single
argument using a typemap. Just do this:
-%apply (char *STRING, int LENGTH) { (char *str, int len) };
+%apply (char *STRING, size_t LENGTH) { (char *str, size_t len) };
...
-int parity(char *str, int len, int initial);
+size_t parity(char *str, size_t len, size_t initial);
@@ -854,6 +854,7 @@ Now, in the target language, you can use binary string data like this:
In the wrapper function, the passed string will be expanded to a pointer and length parameter.
+The (char *STRING, int LENGTH) multi-argument typemap is also available in addition to (char *STRING, size_t LENGTH).
8.3.3 Using %newobject to release memory
diff --git a/Examples/test-suite/char_binary.i b/Examples/test-suite/char_binary.i
new file mode 100644
index 000000000..778792946
--- /dev/null
+++ b/Examples/test-suite/char_binary.i
@@ -0,0 +1,29 @@
+/*
+A test case for testing non null terminated char pointers.
+*/
+
+%module char_binary
+
+%apply (char *STRING, size_t LENGTH) { (const char *str, size_t len) }
+
+%inline %{
+struct Test {
+ size_t strlen(const char *str, size_t len) {
+ return len;
+ }
+};
+
+typedef char namet[5];
+namet var_namet;
+
+typedef char* pchar;
+pchar var_pchar;
+%}
+
+// Remove string handling typemaps and treat as pointer
+%typemap(freearg) SWIGTYPE * ""
+%apply SWIGTYPE * { char * }
+
+%include "carrays.i"
+%array_functions(char, pchar);
+
diff --git a/Examples/test-suite/java/char_binary_runme.java b/Examples/test-suite/java/char_binary_runme.java
new file mode 100644
index 000000000..9227f8617
--- /dev/null
+++ b/Examples/test-suite/java/char_binary_runme.java
@@ -0,0 +1,24 @@
+import char_binary.*;
+
+public class char_binary_runme {
+
+ static {
+ try {
+ System.loadLibrary("char_binary");
+ } 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();
+ byte[] hile = "hile".getBytes();
+ byte[] hil0 = "hil\0".getBytes();
+ if (t.strlen(hile) != 4)
+ throw new RuntimeException("bad multi-arg typemap");
+
+ if (t.strlen(hil0) != 4)
+ throw new RuntimeException("bad multi-arg typemap");
+ }
+}
diff --git a/Examples/test-suite/perl5/char_binary_runme.pl b/Examples/test-suite/perl5/char_binary_runme.pl
new file mode 100755
index 000000000..4c50ee700
--- /dev/null
+++ b/Examples/test-suite/perl5/char_binary_runme.pl
@@ -0,0 +1,32 @@
+use strict;
+use warnings;
+use Test::More tests => 7;
+BEGIN { use_ok('char_binary') }
+require_ok('char_binary');
+
+my $t = char_binary::Test->new();
+
+is($t->strlen('hile'), 4, "string typemap");
+
+is($t->strlen("hil\0"), 4, "string typemap");
+
+#
+# creating a raw char*
+#
+my $pc = char_binary::new_pchar(5);
+char_binary::pchar_setitem($pc, 0, 'h');
+char_binary::pchar_setitem($pc, 1, 'o');
+char_binary::pchar_setitem($pc, 2, 'l');
+char_binary::pchar_setitem($pc, 3, 'a');
+char_binary::pchar_setitem($pc, 4, 0);
+
+
+is($t->strlen($pc), 4, "string typemap");
+
+$char_binary::var_pchar = $pc;
+is($char_binary::var_pchar, "hola", "pointer case");
+
+$char_binary::var_namet = $pc;
+is($char_binary::var_namet, "hola", "pointer case");
+
+char_binary::delete_pchar($pc);
diff --git a/Examples/test-suite/perl5/primitive_types_runme.pl b/Examples/test-suite/perl5/primitive_types_runme.pl
index 6d7b05d8d..31604ad06 100755
--- a/Examples/test-suite/perl5/primitive_types_runme.pl
+++ b/Examples/test-suite/perl5/primitive_types_runme.pl
@@ -1,6 +1,6 @@
use strict;
use warnings;
-use Test::More tests => 54;
+use Test::More tests => 51;
BEGIN { use_ok('primitive_types') }
require_ok('primitive_types');
@@ -179,11 +179,6 @@ $t->{var_namet} = 'hol';
is($t->{var_namet}, 'hol', "namet");
-is($t->strlen('hile'), 4, "string typemap");
-
-is($t->strlen("hil\0"), 4, "string typemap");
-
-
$primitive_types::var_char = "\0";
is($primitive_types::var_char, "\0", "char '0' case");
@@ -220,8 +215,6 @@ primitive_types::pchar_setitem($pc, 3, 'a');
primitive_types::pchar_setitem($pc, 4, 0);
-is($t->strlen($pc), 4, "string typemap");
-
$primitive_types::var_pchar = $pc;
is($primitive_types::var_pchar, "hola", "pointer case");
diff --git a/Examples/test-suite/primitive_types.i b/Examples/test-suite/primitive_types.i
index e00108b93..f912bd77c 100644
--- a/Examples/test-suite/primitive_types.i
+++ b/Examples/test-suite/primitive_types.i
@@ -355,8 +355,6 @@ macro(size_t, pfx, sizet)
%enddef
-%apply (char *STRING, int LENGTH) { (const char *str, size_t len) }
-
%inline {
struct Foo
{
@@ -464,15 +462,8 @@ macro(size_t, pfx, sizet)
%test_prim_types_ovr(ovr_decl, ovr)
- size_t strlen(const char *str, size_t len)
- {
- return len;
- }
-
static const double stc_double;
static const double stc_float;
-
-
};
struct TestDirector
diff --git a/Examples/test-suite/python/char_binary_runme.py b/Examples/test-suite/python/char_binary_runme.py
new file mode 100644
index 000000000..b6d9c81c8
--- /dev/null
+++ b/Examples/test-suite/python/char_binary_runme.py
@@ -0,0 +1,36 @@
+from char_binary import *
+
+t = Test()
+if t.strlen('hile') != 4:
+ print t.strlen('hile')
+ raise RuntimeError, "bad multi-arg typemap"
+
+if t.strlen('hil\0') != 4:
+ raise RuntimeError, "bad multi-arg typemap"
+
+#
+# creating a raw char*
+#
+pc = new_pchar(5)
+pchar_setitem(pc, 0, 'h')
+pchar_setitem(pc, 1, 'o')
+pchar_setitem(pc, 2, 'l')
+pchar_setitem(pc, 3, 'a')
+pchar_setitem(pc, 4, 0)
+
+
+if t.strlen(pc) != 4:
+ raise RuntimeError, "bad multi-arg typemap"
+
+cvar.var_pchar = pc
+if cvar.var_pchar != "hola":
+ print cvar.var_pchar
+ raise RuntimeError, "bad pointer case"
+
+cvar.var_namet = pc
+#if cvar.var_namet != "hola\0":
+if cvar.var_namet != "hola":
+ raise RuntimeError, "bad pointer case"
+
+delete_pchar(pc)
+
diff --git a/Examples/test-suite/python/primitive_types_runme.py b/Examples/test-suite/python/primitive_types_runme.py
index 02cc21763..2495cd60d 100644
--- a/Examples/test-suite/python/primitive_types_runme.py
+++ b/Examples/test-suite/python/primitive_types_runme.py
@@ -188,14 +188,6 @@ if t.var_namet != 'hol':
raise RuntimeError
-if t.strlen('hile') != 4:
- print t.strlen('hile')
- raise RuntimeError, "bad string typemap"
-
-if t.strlen('hil\0') != 4:
- raise RuntimeError, "bad string typemap"
-
-
cvar.var_char = '\0'
if cvar.var_char != '\0':
raise RuntimeError, "bad char '0' case"
@@ -244,9 +236,6 @@ pchar_setitem(pc, 3, 'a')
pchar_setitem(pc, 4, 0)
-if t.strlen(pc) != 4:
- raise RuntimeError, "bad string typemap"
-
cvar.var_pchar = pc
if cvar.var_pchar != "hola":
print cvar.var_pchar
diff --git a/Lib/chicken/chicken.swg b/Lib/chicken/chicken.swg
index 112780499..525c1a64c 100644
--- a/Lib/chicken/chicken.swg
+++ b/Lib/chicken/chicken.swg
@@ -538,7 +538,7 @@ $result = C_SCHEME_UNDEFINED;
* String & length
* ------------------------------------------------------------ */
-%typemap(in) (char *STRING, int LENGTH) {
+%typemap(in) (char *STRING, int LENGTH), (char *STRING, size_t LENGTH) {
if ($input == C_SCHEME_FALSE) {
swig_barf (SWIG_BARF1_BAD_ARGUMENT_TYPE, "Cannot use a null/#f string for a char*, int arguments");
}
diff --git a/Lib/guile/typemaps.i b/Lib/guile/typemaps.i
index c194d4bc9..c31f1463f 100644
--- a/Lib/guile/typemaps.i
+++ b/Lib/guile/typemaps.i
@@ -348,7 +348,7 @@ typedef unsigned long SCM;
* String & length
* ------------------------------------------------------------ */
-%typemap(in) (char *STRING, int LENGTH) {
+%typemap(in) (char *STRING, int LENGTH), (char *STRING, size_t LENGTH) {
size_t temp;
$1 = ($1_ltype) gh_scm2newstr($input, &temp);
$2 = ($2_ltype) temp;
diff --git a/Lib/java/java.swg b/Lib/java/java.swg
index 44e1337bc..159aafb17 100644
--- a/Lib/java/java.swg
+++ b/Lib/java/java.swg
@@ -1290,6 +1290,21 @@ SWIG_PROXY_CONSTRUCTOR(true, true, SWIGTYPE)
/* const pointers */
%apply SWIGTYPE * { SWIGTYPE *const }
+/* String & length */
+%typemap(jni) (char *STRING, size_t LENGTH) "jbyteArray"
+%typemap(jtype) (char *STRING, size_t LENGTH) "byte[]"
+%typemap(jstype) (char *STRING, size_t LENGTH) "byte[]"
+%typemap(javain) (char *STRING, size_t LENGTH) "$javainput"
+%typemap(freearg) (char *STRING, size_t LENGTH) ""
+%typemap(in) (char *STRING, size_t LENGTH) {
+ $1 = (char *) JCALL2(GetByteArrayElements, jenv, $input, 0);
+ $2 = (size_t) JCALL1(GetArrayLength, jenv, $input);
+}
+%typemap(argout) (char *STRING, size_t LENGTH) {
+ JCALL3(ReleaseByteArrayElements, jenv, $input, (jbyte *)$1, 0);
+}
+%apply (char *STRING, size_t LENGTH) { (char *STRING, int LENGTH) }
+
/* java keywords */
%include
diff --git a/Lib/php/php.swg b/Lib/php/php.swg
index f4cc8d2b2..ed336d6d2 100644
--- a/Lib/php/php.swg
+++ b/Lib/php/php.swg
@@ -76,8 +76,7 @@
$1 = ($1_ltype) Z_STRVAL_PP($input);
}
-%typemap(in) (char *STRING, int LENGTH)
-{
+%typemap(in) (char *STRING, int LENGTH), (char *STRING, size_t LENGTH) {
convert_to_string_ex($input);
$1 = ($1_ltype) Z_STRVAL_PP($input);
$2 = ($2_ltype) Z_STRLEN_PP($input);
diff --git a/Lib/pike/pike.swg b/Lib/pike/pike.swg
index 0cfec52b0..130af1346 100644
--- a/Lib/pike/pike.swg
+++ b/Lib/pike/pike.swg
@@ -185,7 +185,7 @@ extern "C" {
* String & length
* ------------------------------------------------------------ */
-%typemap(in, pikedesc="tStr") (char *STRING, int LENGTH) {
+%typemap(in) (char *STRING, int LENGTH), (char *STRING, size_t LENGTH) {
if ($input.type != T_STRING)
Pike_error("Bad argument: Expected a string.\n");
$1 = ($1_ltype) STR0($input.u.string);