
>>> make_upper("hello world")
'HELLO WORLD'
>>> attach_header("Hello world")
'header: Hello world'
>>>
This macro differs from %cstring_bounded_mutable() in that a
buffer is dynamically allocated (on the heap using
malloc/new). This buffer is always large enough to store a
copy of the input value plus any expansion bytes that might have been
requested.
It is important to emphasize that this function
does not directly mutate the string value passed---instead it makes a copy of the
input value, mutates it, and returns it as a result.
If the function expands the result by more than expansion extra
bytes, then the program will crash with a buffer overflow!
%cstring_output_maxsize(parm, maxparm)
This macro is used to handle bounded character output functions where both a char * and a maximum length parameter are provided. As input, a user simply supplies the maximum length. The return value is assumed to be a NULL-terminated string.In the target language:%cstring_output_maxsize(char *path, int maxpath); ... void get_path(char *path, int maxpath);This macro provides a safer alternative for functions that need to write string data into a buffer. User supplied buffer size is used to dynamically allocate memory on heap. Results are placed into that buffer and returned as a string object.>>> get_path(1024) '/home/beazley/Packages/Foo/Bar' >>>
%cstring_output_withsize(parm, maxparm)
This macro is used to handle bounded character output functions where both a char * and a pointer int * are passed. Initially, the int * parameter points to a value containing the maximum size. On return, this value is assumed to contain the actual number of bytes. As input, a user simply supplies the maximum length. The output value is a string that may contain binary data.In the target language:%cstring_output_withsize(char *data, int *maxdata); ... void get_data(char *data, int *maxdata);This macro is a somewhat more powerful version of %cstring_output_chunk(). Memory is dynamically allocated and can be arbitrary large. Furthermore, a function can control how much data is actually returned by changing the value of the maxparm argument.>>> get_data(1024) 'x627388912' >>> get_data(1024) 'xyzzy' >>>
%cstring_output_allocate(parm, release)
This macro is used to return strings that are allocated within the program and returned in a parameter of type char **. For example:The returned string is assumed to be NULL-terminated. release specifies how the allocated memory is to be released (if applicable). Here is an example:void foo(char **s) { *s = (char *) malloc(64); sprintf(*s, "Hello world\n"); }In the target language:%cstring_output_allocate(char **s, free(*$1)); ... void foo(char **s);>>> foo() 'Hello world\n' >>>
%cstring_output_allocate_size(parm, szparm, release)
This macro is used to return strings that are allocated within the program and returned in two parameters of type char ** and int *. For example:Comments:The returned string may contain binary data. release specifies how the allocated memory is to be released (if applicable). Here is an example:void foo(char **s, int *sz) { *s = (char *) malloc(64); *sz = 64; // Write some binary data ... }In the target language:%cstring_output_allocate_size(char **s, int *slen, free(*$1)); ... void foo(char **s, int *slen);This is the safest and most reliable way to return binary string data in SWIG. If you have functions that conform to another prototype, you might consider wrapping them with a helper function. For example, if you had this:>>> foo() '\xa9Y:\xf6\xd7\xe1\x87\xdbH;y\x97\x7f"\xd3\x99\x14V\xec\x06\xea\xa2\x88' >>>You could wrap it with a function like this:char *get_data(int *len);void my_get_data(char **result, int *len) { *result = get_data(len); }
In the target language:%module example %include "std_string.i" std::string foo(); void bar(const std::string &x);
x = foo(); # Returns a string object
bar("Hello World"); # Pass string as std::string
This module only supports types std::string and
const std::string &. Pointers and non-const references
are left unmodified and returned as SWIG pointers.
This library file is fully aware of C++ namespaces. If you export std::string or rename it with a typedef, make sure you include those declarations in your interface. For example:
Note: The std_string library is incompatible with Perl on some platforms. We're looking into it.%module example %include "std_string.i" using namespace std; typedef std::string String; ... void foo(string s, const String &t); // std_string typemaps still applied
%module example
%include "std_vector.i"
namespace std {
%template(vectori) vector<int>;
%template(vectord) vector<double>;
};
When a template vector<X> is instantiated a number of things happen:
/* File : example.h */
#include <vector>
#include <algorithm>
#include <functional>
#include <numeric>
double average(std::vector<int> v) {
return std::accumulate(v.begin(),v.end(),0.0)/v.size();
}
std::vector<double> half(const std::vector<double>& v) {
std::vector<double> w(v);
for (unsigned int i=0; i<w.size(); i++)
w[i] /= 2.0;
return w;
}
void halve_in_place(std::vector<double>& v) {
std::transform(v.begin(),v.end(),v.begin(),
std::bind2nd(std::divides<double>(),2.0));
}
To wrap with SWIG, you might write the following:
%module example
%{
#include "example.h"
%}
%include "std_vector.i"
// Instantiate templates used by example
namespace std {
%template(IntVector) vector<int>;
%template(DoubleVector) vector<double>;
}
// Include the header file with above prototypes
%include "example.h"
Now, to illustrate the behavior in the scripting interpreter, consider this Python example:
>>> from example import *
>>> iv = IntVector(4) # Create an vector<int>
>>> for i in range(0,4):
... iv[i] = i
>>> average(iv) # Call method
1.5
>>> average([0,1,2,3]) # Call with list
1.5
>>> half([1,2,3]) # Half a list
(0.5,1.0,1.5)
>>> halve_in_place([1,2,3]) # Oops
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: Type error. Expected _p_std__vectorTdouble_t
>>> dv = DoubleVector(4)
>>> for i in range(0,4):
... dv[i] = i
>>> halve_in_place(dv) # Ok
>>> for i in dv:
... print i
...
0.0
0.5
1.0
1.5
>>> dv[20] = 4.5
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "example.py", line 81, in __setitem__
def __setitem__(*args): return apply(examplec.DoubleVector___setitem__,args)
IndexError: vector index out of range
>>>
This library module is fully aware of C++ namespaces. If you use vectors with other names,
make sure you include the appropriate using or typedef directives. For example:
%include "std_vector.i"
namespace std {
%template(IntVector) vector<int>;
}
using namespace std;
typedef std::vector Vector;
void foo(vector<int> *x, const Vector &x);
Note: This module makes use of several advanced SWIG features including templatized typemaps and template partial specialization. If you are tring to wrap other C++ code with templates, you might look at the code contained in std_vector.i. Alternatively, you can show them the code if you want to make their head explode.
Note: This module is defined for all SWIG target languages. However argument conversion details and the public API exposed to the interpreter vary.
Note: std_vector.i was written by Luigi "The Amazing" Ballabio.
SWIG_exception(int code, const char *message)
Raises an exception in the target language. code is one of the following symbolic constants:The primary use of this module is in writing language-independent exception handlers. For example:message is a string indicating more information about the problem.SWIG_MemoryError SWIG_IOError SWIG_RuntimeError SWIG_IndexError SWIG_TypeError SWIG_DivisionByZero SWIG_OverflowError SWIG_SyntaxError SWIG_ValueError SWIG_SystemError
%include "exception.i"
%exception std::vector::getitem {
try {
$action
} catch (std::out_of_range& e) {
SWIG_exception(SWIG_IndexError,const_cast<char*>(e.what()));
}
}