Files
ortools-clone/util/data.swig
lperron@google.com e6b1c2755f better swig docs
2011-12-05 14:15:08 +00:00

549 lines
18 KiB
Plaintext

// Copyright 2010-2011 Google
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
%include base/base.swig
%{
#include <vector>
#include "base/callback.h"
#include "base/integral_types.h"
using std::string;
%}
#if defined(SWIGPYTHON)
namespace operations_research {
// ----- Callback Wrapping -----
%{
static string PyCallbackString(PyObject* pyfunc) {
string result;
PyObject* arglist = Py_BuildValue("()");
PyObject* pyresult = PyEval_CallObject(pyfunc, arglist);
Py_DECREF(arglist);
if (pyresult) {
result = PyString_AsString(pyresult);
Py_DECREF(pyresult);
}
return result;
}
%}
%typemap(in) ResultCallback<string>* {
if (!PyCallable_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Need a callable object!");
SWIG_fail;
}
$1 = NewPermanentCallback(&PyCallbackString, $input);
}
%{
static int64 PyCallback1Int64Int64(PyObject* pyfunc, int64 i) {
int64 result = 0;
// Cast to int needed, no int64 support
// () needed to force creation of one-element tuple
PyObject* arglist = Py_BuildValue("(l)", static_cast<int>(i));
PyObject* pyresult = PyEval_CallObject(pyfunc, arglist);
Py_DECREF(arglist);
if (pyresult) {
result = PyInt_AsLong(pyresult);
}
Py_XDECREF(pyresult);
return result;
}
%}
%typemap(in) ResultCallback1<int64, int64>* {
if (!PyCallable_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Need a callable object!");
SWIG_fail;
}
$1 = NewPermanentCallback(&PyCallback1Int64Int64, $input);
}
%{
static int64 PyCallback2Int64Int64Int64(PyObject* pyfunc, int64 i, int64 j) {
int64 result = 0;
// Cast to int needed, no int64 support
PyObject* arglist = Py_BuildValue("ll",
static_cast<int>(i),
static_cast<int>(j));
PyObject* pyresult = PyEval_CallObject(pyfunc, arglist);
Py_DECREF(arglist);
if (pyresult) {
result = PyInt_AsLong(pyresult);
}
Py_XDECREF(pyresult);
return result;
}
%}
%typemap(in) ResultCallback2<int64, int64, int64>* {
if (!PyCallable_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Need a callable object!");
SWIG_fail;
}
$1 = NewPermanentCallback(&PyCallback2Int64Int64Int64, $input);
}
%{
static int64 PyCallback3Int64Int64Int64Int64(PyObject* pyfunc,
int64 i, int64 j, int64 k) {
int64 result = 0;
// Cast to int needed, no int64 support
PyObject* arglist = Py_BuildValue("lll",
static_cast<int>(i),
static_cast<int>(j),
static_cast<int>(k));
PyObject* pyresult = PyEval_CallObject(pyfunc, arglist);
Py_DECREF(arglist);
if (pyresult) {
result = PyInt_AsLong(pyresult);
}
Py_XDECREF(pyresult);
return result;
}
%}
%typemap(in) ResultCallback3<int64, int64, int64, int64>* {
if (!PyCallable_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Need a callable object!");
SWIG_fail;
}
$1 = NewPermanentCallback(&PyCallback3Int64Int64Int64Int64, $input);
}
%{
static bool PyCallbackBool(PyObject* pyfunc) {
bool result = false;
// "()" needed to force creation of empty argument list
PyObject* arglist = Py_BuildValue("()");
PyObject* pyresult = PyEval_CallObject(pyfunc, arglist);
Py_DECREF(arglist);
if (pyresult) {
// no PyBool_AsBool so do this instead:
if (pyresult == Py_True) {
result = true;
} else {
result = false;
}
}
Py_XDECREF(pyresult);
return result;
}
%}
%typemap(in) ResultCallback<bool>* {
if (!PyCallable_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Need a callable object!");
SWIG_fail;
}
$1 = NewPermanentCallback(&PyCallbackBool, $input);
}
// ----- std::vector<data> wrapping -----
// Add conversion rules for std::vector<int64>.
%typemap(in) const std::vector<int64>& (std::vector<int64> temp) {
if (!PyTuple_Check($input) && !PyList_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Expecting a sequence");
SWIG_fail;
}
bool is_tuple = PyTuple_Check($input);
temp.resize(is_tuple ? PyTuple_Size($input) : PyList_Size($input));
for (size_t i = 0; i < temp.size(); ++i) {
temp[i] = PyInt_AsLong(is_tuple ? PyTuple_GetItem($input, i) :
PyList_GetItem($input, i));
}
$1 = &temp;
}
%typecheck(SWIG_TYPECHECK_POINTER) const std::vector<int64>& {
if (!PyTuple_Check($input) && !PyList_Check($input)) {
$1 = 0;
} else {
const bool is_tuple = PyTuple_Check($input);
const int size = is_tuple ? PyTuple_Size($input) : PyList_Size($input);
bool failed = false;
for (size_t i = 0; i < size; ++i) {
PyObject* const obj =
is_tuple ? PyTuple_GetItem($input, i) : PyList_GetItem($input, i);
if (!PyInt_Check(obj) && !PyLong_Check(obj)) {
failed = true;
break;
}
}
$1 = failed ? 0 : 1;
}
}
// Add conversion list(tuple(int)) -> std::vector<vector>.
%typemap(in) const std::vector<std::vector<int64> >&
(std::vector<std::vector<int64> > temp) {
if (!PyList_Check($input)) {
PyErr_SetString(PyExc_TypeError, "Expecting a list of tuples");
SWIG_fail;
}
int len = PyList_Size($input);
int arity = -1;
if (len > 0) {
temp.resize(len);
for (size_t i = 0; i < len; ++i) {
PyObject *tuple = PyList_GetItem($input, i);
if (!PyTuple_Check(tuple) && !PyList_Check(tuple)) {
PyErr_SetString(PyExc_TypeError, "Expecting a sequence");
SWIG_fail;
}
bool is_tuple = PyTuple_Check(tuple);
int local_arity = is_tuple ? PyTuple_Size(tuple) : PyList_Size(tuple);
if (arity != -1 && arity != local_arity) {
PyErr_SetString(PyExc_TypeError, "Tuples should have the same arity");
SWIG_fail;
}
if (arity == -1) {
arity = local_arity;
}
temp[i].resize(arity);
for (size_t j = 0; j < local_arity; ++j) {
temp[i][j] = PyInt_AsLong(is_tuple ?
PyTuple_GetItem(tuple, j) :
PyList_GetItem(tuple, j));
}
}
}
$1 = &temp;
}
%typecheck(SWIG_TYPECHECK_POINTER) const std::vector<std::vector<int64> >& {
if (!PyList_Check($input)) {
$1 = 0;
} else {
const int size = PyList_Size($input);
bool failed = false;
for (size_t i = 0; i < size; ++i) {
PyObject* const tuple = PyList_GetItem($input, i);
if (!PyTuple_Check(tuple) && !PyList_Check(tuple)) {
$1 = 0;
break;
} else {
const bool is_tuple = PyTuple_Check(tuple);
const int arity = is_tuple ? PyTuple_Size(tuple) : PyList_Size(tuple);
for (size_t j = 0; j < arity; ++j) {
PyObject* const entry =
is_tuple ? PyTuple_GetItem(tuple, j) : PyList_GetItem(tuple, j);
if (!PyInt_Check(entry) && !PyLong_Check(entry)) {
failed = true;
break;
}
}
}
if (failed) {
break;
}
}
$1 = failed ? 0 : 1;
}
}
} // namespace operations_research
#endif // SWIGPYTHON
#if defined(SWIGJAVA)
%{
#include "base/jniutil.h"
#include "base/scoped_ptr.h"
%}
%module(directors="1") main
%feature("director") LongResultCallback1;
%feature("director") LongResultCallback2;
%feature("director") LongResultCallback3;
%{
#include <vector>
#include "base/callback.h"
#include "base/integral_types.h"
// When a director is created for a class with SWIG, the C++ part of the
// director keeps a JNI global reference to the Java part. This global reference
// only gets deleted in the destructor of the C++ part, but by default, this
// only happens when the Java part is processed by the GC (however, this never
// happens, because there is the JNI global reference...).
//
// To break the cycle, it is necessary to delete the C++ part manually. For the
// callback classes, this is done by deriving them from the respective C++
// ResultCallback classes. When the java callback class is asked for a C++
// callback class, it hands over its C++ part. It is expected, that whoever
// receives the C++ callback class, owns it and destroys it after they no longer
// need it. But by destroying it, they also break the reference cycle and the
// Java part may be processed by the GC.
//
// However, this behavior also means that the callback class can only be used
// in one context and that if its C++ callback class is not received by someone
// who destroys it in the end, it will stay in memory forever.
class LongResultCallback1 : private ResultCallback1<int64, int64> {
public:
LongResultCallback1() : used_as_permanent_handler_(false) {}
virtual int64 run(int64) = 0;
ResultCallback1<int64, int64>* GetPermanentCallback() {
CHECK(!used_as_permanent_handler_);
used_as_permanent_handler_ = true;
return this;
}
virtual ~LongResultCallback1() {}
private:
virtual bool IsRepeatable() const { return true; }
virtual int64 Run(int64 i) {
return run(i);
}
bool used_as_permanent_handler_;
};
class LongResultCallback2 : private ResultCallback2<int64, int64, int64> {
public:
LongResultCallback2() : used_as_permanent_handler_(false) {}
virtual ~LongResultCallback2() {}
virtual int64 run(int64, int64) = 0;
ResultCallback2<int64, int64, int64>* GetPermanentCallback() {
CHECK(!used_as_permanent_handler_);
used_as_permanent_handler_ = true;
return this;
}
private:
virtual bool IsRepeatable() const { return true; }
virtual int64 Run(int64 i, int64 j) {
return run(i, j);
}
bool used_as_permanent_handler_;
};
class LongResultCallback3 : private ResultCallback3<int64, int64, int64, int64> {
public:
LongResultCallback3() : used_as_permanent_handler_(false) {}
virtual ~LongResultCallback3() {}
virtual int64 run(int64, int64, int64) = 0;
ResultCallback3<int64, int64, int64, int64>* GetPermanentCallback() {
CHECK(!used_as_permanent_handler_);
used_as_permanent_handler_ = true;
return this;
}
private:
virtual bool IsRepeatable() const { return true; }
virtual int64 Run(int64 i, int64 j, int64 k) {
return run(i, j, k);
}
bool used_as_permanent_handler_;
};
%}
class LongResultCallback1 : private ResultCallback1<int64, int64> {
public:
virtual int64 run(int64) = 0;
ResultCallback1<int64, int64>* GetPermanentCallback();
virtual ~LongResultCallback1();
private:
virtual bool IsRepeatable() const;
virtual int64 Run(int64 i);
bool used_as_permanent_handler_;
};
class LongResultCallback2 : private ResultCallback2<int64, int64, int64> {
public:
virtual int64 run(int64, int64) = 0;
ResultCallback2<int64, int64, int64>* GetPermanentCallback();
virtual ~LongResultCallback2();
private:
virtual bool IsRepeatable() const;
virtual int64 Run(int64 i, int64 j);
bool used_as_permanent_handler_;
};
class LongResultCallback3 : private ResultCallback3<int64, int64, int64, int64> {
public:
virtual int64 run(int64, int64, int64) = 0;
ResultCallback3<int64, int64, int64, int64>* GetPermanentCallback();
virtual ~LongResultCallback3();
private:
virtual bool IsRepeatable() const;
virtual int64 Run(int64 i, int64 j, int64 k);
bool used_as_permanent_handler_;
};
// Typemaps for callbacks in java.
%typemap(jstype) ResultCallback1<int64, int64>* "LongResultCallback1";
%typemap(javain) ResultCallback1<int64, int64>* "SWIGTYPE_p_ResultCallback1Tlong_long_long_long_t.getCPtr($javainput.GetPermanentCallback())";
%typemap(jstype) ResultCallback2<int64, int64, int64>* "LongResultCallback2";
%typemap(javain) ResultCallback2<int64, int64, int64>* "SWIGTYPE_p_ResultCallback2Tlong_long_long_long_long_long_t.getCPtr($javainput.GetPermanentCallback())";
%typemap(jstype) ResultCallback3<int64, int64, int64, int64>*
"LongResultCallback3";
%typemap(javain) ResultCallback3<int64, int64, int64, int64>*
"SWIGTYPE_p_ResultCallback3Tlong_long_long_long_long_long_long_long_t.getCPtr($javainput.GetPermanentCallback())";
// Typemaps to represent const std::vector<int64>& arguments as arrays of long.
%typemap(jni) const std::vector<int64>& "jobjectArray"
%typemap(jtype) const std::vector<int64>& "long[]"
%typemap(jstype) const std::vector<int64>& "long[]"
%typemap(javain) const std::vector<int64>& "$javainput"
%typemap(in) const std::vector<int64>& %{
if($input) {
$1 = new std::vector<int64>;
int size = jenv->GetArrayLength($input);
jlong *values = jenv->GetLongArrayElements((jlongArray)$input, NULL);
for (int i = 0; i < size; ++i) {
long value = values[i];
$1->push_back(value);
}
jenv->ReleaseLongArrayElements((jlongArray)$input, values, JNI_ABORT);
}
else {
SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null table");
return $null;
}
%}
%typemap(freearg) const std::vector<int64>& {
delete $1;
}
// Typemaps to represent const std::vector<int>& arguments as arrays of long.
%typemap(jni) const std::vector<int>& "jobjectArray"
%typemap(jtype) const std::vector<int>& "int[]"
%typemap(jstype) const std::vector<int>& "int[]"
%typemap(javain) const std::vector<int>& "$javainput"
%typemap(in) const std::vector<int>& %{
if($input) {
$1 = new std::vector<int>;
int size = jenv->GetArrayLength($input);
jint *values = jenv->GetIntArrayElements((jintArray)$input, NULL);
for (int i = 0; i < size; ++i) {
int value = values[i];
$1->push_back(value);
}
jenv->ReleaseIntArrayElements((jintArray)$input, values, JNI_ABORT);
}
else {
SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null table");
return $null;
}
%}
%typemap(freearg) const std::vector<int>& {
delete $1;
}
// Convert long[][] to std::vector<std::vector<int64> >
%typemap(jni) const std::vector<std::vector<int64> >& "jobjectArray"
%typemap(jtype) const std::vector<std::vector<int64> >& "long[][]"
%typemap(jstype) const std::vector<std::vector<int64> >& "long[][]"
%typemap(javain) const std::vector<std::vector<int64> >& "$javainput"
%typemap(in) const std::vector<std::vector<int64> >& (std::vector<std::vector<int64> > result) {
const int size = jenv->GetArrayLength($input);
result.clear();
result.resize(size);
for (int index1 = 0; index1 < size; ++index1) {
jlongArray inner_array =
(jlongArray)jenv->GetObjectArrayElement($input, index1);
const int tuple_size = jenv->GetArrayLength(inner_array);
jlong* const values =
jenv->GetLongArrayElements((jlongArray)inner_array, NULL);
for (int index2 = 0; index2 < tuple_size; ++index2) {
const int64 value = values[index2];
result[index1].push_back(value);
}
jenv->ReleaseLongArrayElements((jlongArray)inner_array, values, JNI_ABORT);
jenv->DeleteLocalRef(inner_array);
}
$1 = &result;
}
// SWIG macros to be used in generating Java wrappers for C++ protocol
// message parameters. Each protocol message is serialized into
// byte[] before passing into (or returning from) C++ code.
// If the C++ function expects an input protocol message:
// foo(const MyProto* message,...)
// Use PROTO_INPUT macro:
// PROTO_INPUT(MyProto, com.google.proto.protos.test.MyProto, message)
//
// if the C++ function returns a protocol message:
// MyProto* foo();
// Use PROTO2_RETURN macro:
// PROTO2_RETURN(MyProto, com.google.proto.protos.test.MyProto, giveOwnership)
// -> the 'giveOwnership' parameter should be true iff the C++ function
// returns a new proto which should be deleted by the client.
// Passing each protocol message from Java to C++ by value. Each ProtocolMessage
// is serialized into byte[] when it is passed from Java to C++, the C++ code
// deserializes into C++ native protocol message.
//
// @param CppProtoType the fully qualified C++ protocol message type
// @param JavaProtoType the corresponding fully qualified Java protocol message
// type
// @param param_name the parameter name
%define PROTO_INPUT(CppProtoType, JavaProtoType, param_name)
%typemap(jni) PROTO_TYPE* INPUT, PROTO_TYPE& INPUT "jbyteArray"
%typemap(jtype) PROTO_TYPE* INPUT, PROTO_TYPE& INPUT "byte[]"
%typemap(jstype) PROTO_TYPE* INPUT, PROTO_TYPE& INPUT "JavaProtoType"
%typemap(javain) PROTO_TYPE* INPUT, PROTO_TYPE& INPUT "$javainput.toByteArray()"
%typemap(in) PROTO_TYPE* INPUT (CppProtoType temp),
PROTO_TYPE& INPUT (CppProtoType temp) {
int proto_size = 0;
scoped_array<char> proto_buffer(
JNIUtil::MakeCharArray(jenv, $input, &proto_size));
bool parsed_ok = temp.ParseFromArray(proto_buffer.get(), proto_size);
if (!parsed_ok) {
SWIG_JavaThrowException(jenv,
SWIG_JavaRuntimeException,
"Unable to parse CppProtoType protocol message.");
}
$1 = &temp;
}
%apply PROTO_TYPE& INPUT { const CppProtoType& param_name }
%apply PROTO_TYPE& INPUT { CppProtoType& param_name }
%apply PROTO_TYPE* INPUT { const CppProtoType* param_name }
%apply PROTO_TYPE* INPUT { CppProtoType* param_name }
%enddef // end PROTO_INPUT
%define PROTO2_RETURN(CppProtoType, JavaProtoType, giveOwnership)
%typemap(jni) CppProtoType* "jbyteArray"
%typemap(jtype) CppProtoType* "byte[]"
%typemap(jstype) CppProtoType* "JavaProtoType"
%typemap(javaout) CppProtoType* {
byte[] buf = $jnicall;
if (buf == null || buf.length == 0) {
return null;
}
try {
return JavaProtoType.parseFrom(buf);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw new RuntimeException(
"Unable to parse JavaProtoType protocol message.");
}
}
%typemap(out) CppProtoType* {
scoped_array<char> buf(new char[$1->ByteSize()]);
$1->SerializeWithCachedSizesToArray(reinterpret_cast<uint8*>(buf.get()));
$result = JNIUtil::MakeJByteArray(jenv, buf.get(), $1->ByteSize());
if (giveOwnership) {
// To prevent a memory leak.
delete $1;
$1 = NULL;
}
}
%enddef // end PROTO2_RETURN
#endif // SWIGJAVA