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);