mirror of
https://github.com/davisking/dlib.git
synced 2024-11-01 10:14:53 +08:00
merged
This commit is contained in:
commit
af88b0d56f
@ -119,8 +119,26 @@ FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/swig.i
|
||||
%module global
|
||||
|
||||
%{
|
||||
#include \"swig_api.h\"
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
static JavaVM *cached_jvm = 0;
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
|
||||
cached_jvm = jvm;
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
static JNIEnv * JNI_GetEnv() {
|
||||
JNIEnv *env;
|
||||
jint rc = cached_jvm->GetEnv((void **)&env, JNI_VERSION_1_6);
|
||||
if (rc == JNI_EDETACHED)
|
||||
throw std::runtime_error(\"current thread not attached\");
|
||||
if (rc == JNI_EVERSION)
|
||||
throw std::runtime_error(\"jni version not supported\");
|
||||
return env;
|
||||
}
|
||||
|
||||
#include \"swig_api.h\"
|
||||
%}
|
||||
|
||||
// Convert all C++ exceptions into java.lang.Exception
|
||||
|
601
dlib/java/java_array.h
Normal file
601
dlib/java/java_array.h
Normal file
@ -0,0 +1,601 @@
|
||||
// Copyright (C) 2017 Davis E. King (davis@dlib.net)
|
||||
// License: Boost Software License See LICENSE.txt for the full license.
|
||||
#ifndef DLIB_SWIG_JAVA_ARRAY_H_
|
||||
#define DLIB_SWIG_JAVA_ARRAY_H_
|
||||
|
||||
|
||||
/*
|
||||
|
||||
This file defines three special classes: array, array_view, and array_view_crit. An
|
||||
array is a simple opaque handle to a java array, like a double[] array. The array_view
|
||||
and array_view_crit objects allow you to access the contents of an array. The
|
||||
interfaces of these objects is shown below, but for an example use, suppose you had an
|
||||
array of int in java and you wanted to pass it to C++. You could create a C++ function
|
||||
like this:
|
||||
|
||||
void my_function(const array_view<int32_t>& array);
|
||||
|
||||
and then within java you could call it with code like this:
|
||||
|
||||
int[] array = new int[100];
|
||||
my_function(array);
|
||||
|
||||
and it will work just like you would expect. The array_view<int32_t> will usually result in
|
||||
the JVM doing a copy in the background. However, you can also declare your function
|
||||
like this:
|
||||
|
||||
void my_function(const array_view_crit<int32_t>& array);
|
||||
|
||||
and still call it the same way in java, however, using array_view_crit<int32_t> will usually
|
||||
not result in any copying, and is therefore very fast. array_view_crit uses the JNI
|
||||
routine GetPrimitiveArrayCritical() to get a lock on the java memory underlying the
|
||||
array. So it will probably prevent the garbage collector from running while your
|
||||
function is executing. The JNI documentation is somewhat vague on the limitations of
|
||||
GetPrimitiveArrayCritical(), saying only that you shouldn't hold the lock on the array
|
||||
for "an extended period" or call back into the JVM. Deciding whether or not this
|
||||
matters in your application is left as an exercise for the reader.
|
||||
|
||||
|
||||
There are two ways you can declare your methods if they take an array_view or
|
||||
array_view_crit. Taking a const reference or a non-const reference. E.g.
|
||||
void my_function(const array_view<int32_t>& array);
|
||||
void my_function(array_view<int32_t>& array);
|
||||
You can't declare them to be by value. The non-const version allows you to modify the
|
||||
contents of the array and the modifications will be visible to java, as you would
|
||||
expect. You can also make functions that take array objects directly, but that's only
|
||||
useful if you want to store the array handle somewhere, like in a member of a long
|
||||
lived class. You can also write functions that return arrays back to java. E.g.
|
||||
array<int32_t> make_an_array(size_t s)
|
||||
{
|
||||
array<int32_t> arr(s);
|
||||
array_view<int32_t> aview(arr);
|
||||
// Use aview to put data into the array and generally do something useful.
|
||||
...
|
||||
return arr;
|
||||
}
|
||||
This would create an array and return it as a java int[] array.
|
||||
|
||||
|
||||
You can also of course use functions taking many arguments, as is normally the case
|
||||
with SWIG. Finally, these classes work with the following primitive types:
|
||||
- int16_t
|
||||
- int32_t
|
||||
- int64_t
|
||||
- char (corresponding to java byte)
|
||||
- float
|
||||
- double
|
||||
|
||||
|
||||
|
||||
|
||||
namespace java
|
||||
{
|
||||
template <typename T>
|
||||
class array
|
||||
{
|
||||
/!*
|
||||
WHAT THIS OBJECT REPRESENTS
|
||||
This is a handle to a java array. I.e. a reference to an array instance in
|
||||
java like a double[] or int[]. It doesn't do anything other than tell you
|
||||
the size of the array and allow you to hold a reference to it.
|
||||
|
||||
To access the array contents, you need to create an array_view or
|
||||
array_view_crit from the array.
|
||||
*!/
|
||||
public:
|
||||
array();
|
||||
/!*
|
||||
ensures
|
||||
- #size() == 0
|
||||
- this array is a null reference, i.e. it doesn't reference any array.
|
||||
*!/
|
||||
|
||||
explicit array(size_t new_size);
|
||||
/!*
|
||||
ensures
|
||||
- #size() == new_size
|
||||
- Allocates a new java array.
|
||||
- This array is a reference to the newly allocated java array object.
|
||||
*!/
|
||||
|
||||
size_t size() const;
|
||||
/!*
|
||||
ensures
|
||||
- returns the number of elements in this java array.
|
||||
*!/
|
||||
|
||||
void swap(array& item);
|
||||
/!*
|
||||
ensures
|
||||
- swaps the state of *this and item.
|
||||
*!/
|
||||
|
||||
array(const array& item);
|
||||
array& operator= (const array& item)
|
||||
array(array&& item);
|
||||
array& operator= (array&& item);
|
||||
/!*
|
||||
ensures
|
||||
- The array is copyable, assignable, and movable. All copies will
|
||||
reference the same underlying array. So the copies are shallow, as is
|
||||
normally the case with java reference semantics.
|
||||
*!/
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
class array_view
|
||||
{
|
||||
/!*
|
||||
WHAT THIS OBJECT REPRESENTS
|
||||
This is a view into a java array object. It allows you to access the
|
||||
values stored in an array and modify them if you want to.
|
||||
|
||||
You should only create array_view objects locally in a function since an
|
||||
array_view is only valid as long as the array it references exists. So
|
||||
don't store array_view objects in the member area of a class or globally.
|
||||
*!/
|
||||
|
||||
public:
|
||||
array_view();
|
||||
/!*
|
||||
ensures
|
||||
- #size() == 0
|
||||
- #data() == nullptr
|
||||
*!/
|
||||
|
||||
array_view(const array<T>& arr, bool might_be_modified=true);
|
||||
/!*
|
||||
ensures
|
||||
- #size() == arr.size()
|
||||
- #data() == a pointer to the beginning of the array data referenced by arr.
|
||||
- When you get a view on a java array, sometimes the JVM will actually
|
||||
give you a pointer to a copy of the original array. You therefore have
|
||||
to tell the JVM if you modified the array when you are done using it. If
|
||||
you say you modified it then the JVM will perform another copy from your
|
||||
memory buffer back into the JVM. The state of might_be_modified controls
|
||||
if we do this. So if you are going to modify the array via this
|
||||
array_view you should set might_be_modified==true.
|
||||
*!/
|
||||
|
||||
size_t size() const;
|
||||
/!*
|
||||
ensures
|
||||
- returns the number of elements in this java array.
|
||||
*!/
|
||||
|
||||
T* data();
|
||||
const T* data() const;
|
||||
/!*
|
||||
ensures
|
||||
- returns a pointer to the beginning of the array. Or nullptr if this is a
|
||||
handle to null, rather than an actual array instance.
|
||||
*!/
|
||||
|
||||
T* begin();
|
||||
T* end();
|
||||
const T* begin() const;
|
||||
const T* end() const;
|
||||
/!*
|
||||
ensures
|
||||
- returns iterators to the start and one-past-the-end of the array, as is
|
||||
the convention for iterator ranges in C++.
|
||||
*!/
|
||||
|
||||
T& operator[](size_t i);
|
||||
const T& operator[](size_t i) const;
|
||||
/!*
|
||||
ensures
|
||||
- returns data()[i]
|
||||
*!/
|
||||
|
||||
private:
|
||||
// this object is non-copyable.
|
||||
array_view(const array_view&);
|
||||
array_view& operator=(const array_view&);
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
class array_view_crit
|
||||
{
|
||||
/!*
|
||||
WHAT THIS OBJECT REPRESENTS
|
||||
This is just like an array_view and has an identical interface. The only
|
||||
difference is that we use the JNI call GetPrimitiveArrayCritical() to get a
|
||||
critical lock on the array's memory. Therefore, using array_view_crit is
|
||||
usually faster than array_view since it avoids any unnecessary copying back
|
||||
and forth between the JVM.
|
||||
|
||||
However, this critical lock can block the JVM's garbage collector from
|
||||
running. So don't create long lived array_view_crit objects.
|
||||
*!/
|
||||
};
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// IMPLEMENTATION DETAILS
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace java
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
class array_view_base
|
||||
{
|
||||
public:
|
||||
array_view_base() = default;
|
||||
|
||||
size_t size() const { return sz; }
|
||||
T* data() { return pdata; }
|
||||
const T* data() const { return pdata; }
|
||||
|
||||
T* begin() { return pdata; }
|
||||
T* end() { return pdata+sz; }
|
||||
const T* begin() const { return pdata; }
|
||||
const T* end() const { return pdata+sz; }
|
||||
|
||||
T& operator[](size_t i) { return pdata[i]; }
|
||||
const T& operator[](size_t i) const { return pdata[i]; }
|
||||
|
||||
protected:
|
||||
T* pdata = nullptr;
|
||||
size_t sz = 0;
|
||||
|
||||
private:
|
||||
// this object is non-copyable
|
||||
array_view_base(const array_view_base&);
|
||||
array_view_base& operator=(const array_view_base&);
|
||||
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
struct find_java_array_type;
|
||||
|
||||
template <> struct find_java_array_type<int16_t> { typedef jshortArray type; };
|
||||
template <> struct find_java_array_type<int32_t> { typedef jintArray type; };
|
||||
template <> struct find_java_array_type<int64_t> { typedef jlongArray type; };
|
||||
template <> struct find_java_array_type<char> { typedef jbyteArray type; };
|
||||
template <> struct find_java_array_type<float> { typedef jfloatArray type; };
|
||||
template <> struct find_java_array_type<double> { typedef jdoubleArray type; };
|
||||
|
||||
jshortArray create_java_array(int16_t, size_t size) { return JNI_GetEnv()->NewShortArray(size); }
|
||||
jintArray create_java_array(int32_t, size_t size) { return JNI_GetEnv()->NewIntArray(size); }
|
||||
jlongArray create_java_array(int64_t, size_t size) { return JNI_GetEnv()->NewLongArray(size); }
|
||||
jbyteArray create_java_array(char, size_t size) { return JNI_GetEnv()->NewByteArray(size); }
|
||||
jfloatArray create_java_array(float, size_t size) { return JNI_GetEnv()->NewFloatArray(size); }
|
||||
jdoubleArray create_java_array(double , size_t size) { return JNI_GetEnv()->NewDoubleArray(size); }
|
||||
|
||||
template <typename T>
|
||||
class array
|
||||
{
|
||||
public:
|
||||
|
||||
typedef typename find_java_array_type<T>::type java_type;
|
||||
|
||||
array() {}
|
||||
|
||||
explicit array(size_t size)
|
||||
{
|
||||
ref = create_java_array(T(),size);
|
||||
is_global_ref = false;
|
||||
}
|
||||
|
||||
array(java_type ref_)
|
||||
{
|
||||
if (ref_)
|
||||
{
|
||||
ref = (java_type)JNI_GetEnv()->NewGlobalRef(ref_);
|
||||
is_global_ref = true;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SWIG
|
||||
array(array&& item)
|
||||
{
|
||||
ref = item.ref;
|
||||
is_global_ref = item.is_global_ref;
|
||||
item.ref = NULL;
|
||||
item.is_global_ref = false;
|
||||
}
|
||||
array& operator= (array&& item)
|
||||
{
|
||||
array(std::move(item)).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
~array()
|
||||
{
|
||||
if (ref)
|
||||
{
|
||||
// Don't delete the reference if it's a local reference, since the only reason
|
||||
// we will normally be using array object's that contain local references
|
||||
// is because we plan on returning the newly constructed array back to the JVM,
|
||||
// which automatically frees local references using the normal JVM garbage
|
||||
// collection scheme.
|
||||
if (is_global_ref)
|
||||
JNI_GetEnv()->DeleteGlobalRef(ref);
|
||||
|
||||
ref = NULL;
|
||||
is_global_ref = false;
|
||||
}
|
||||
}
|
||||
|
||||
size_t size() const
|
||||
{
|
||||
if (ref)
|
||||
return JNI_GetEnv()->GetArrayLength(ref);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
array(const array& item)
|
||||
{
|
||||
array(item.ref).swap(*this);
|
||||
}
|
||||
|
||||
array& operator= (const array& item)
|
||||
{
|
||||
array(item).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator java_type() const { return ref;}
|
||||
|
||||
void swap(array& item) { std::swap(ref, item.ref); }
|
||||
|
||||
private:
|
||||
java_type ref = NULL;
|
||||
bool is_global_ref = false;
|
||||
};
|
||||
|
||||
#ifdef SWIG
|
||||
// Tell SWIG to not use it's SwigValueWrapper stuff on array objects since they aren't
|
||||
// needed and it causes superfluous construction and destruction of array objects.
|
||||
%feature("novaluewrapper") array<int16_t>;
|
||||
%template() array<int16_t>;
|
||||
%feature("novaluewrapper") array<int32_t>;
|
||||
%template() array<int32_t>;
|
||||
%feature("novaluewrapper") array<int64_t>;
|
||||
%template() array<int64_t>;
|
||||
%feature("novaluewrapper") array<char>;
|
||||
%template() array<char>;
|
||||
%feature("novaluewrapper") array<float>;
|
||||
%template() array<float>;
|
||||
%feature("novaluewrapper") array<double>;
|
||||
%template() array<double>;
|
||||
#endif
|
||||
|
||||
#ifdef SWIG
|
||||
%define tostring(token)
|
||||
#token
|
||||
%enddef
|
||||
|
||||
%define define_javaObjectRef_converion(type, java_type)
|
||||
// Define array conversions for non-const arrays
|
||||
%typemap(jtype) (array<type>) "java_type[]"
|
||||
%typemap(jstype) (array<type>) "java_type[]"
|
||||
%typemap(jni) (array<type>) tostring(j##java_type##Array)
|
||||
%typemap(javain) (array<type>) "$javainput"
|
||||
%typemap(in) (array<type>) { $1 = array<type>($input); }
|
||||
%typemap(javaout) (array<type>) {return $jnicall; }
|
||||
%typemap(out) (array<type>) {jresult = result;}
|
||||
|
||||
%typemap(jtype) (array<type>&) "java_type[]"
|
||||
%typemap(jstype) (array<type>&) "java_type[]"
|
||||
%typemap(jni) (array<type>&) tostring(j##java_type##Array)
|
||||
%typemap(javain) (array<type>&) "$javainput"
|
||||
%typemap(arginit) (array<type>&) { $1 = &temp$argnum; }
|
||||
%typemap(in) (array<type>&) (array<type> temp) { *($1) = array<type>($input); }
|
||||
|
||||
%typemap(jtype) (const array<type>&) "java_type[]"
|
||||
%typemap(jstype) (const array<type>&) "java_type[]"
|
||||
%typemap(jni) (const array<type>&) tostring(j##java_type##Array)
|
||||
%typemap(javain) (const array<type>&) "$javainput"
|
||||
%typemap(arginit) (const array<type>&) { $1 = &temp$argnum; }
|
||||
%typemap(in) (const array<type>&) (array<type> temp) { *($1) = array<type>($input); }
|
||||
%enddef
|
||||
define_javaObjectRef_converion(int16_t,short)
|
||||
define_javaObjectRef_converion(int32_t,int)
|
||||
define_javaObjectRef_converion(int64_t,long)
|
||||
define_javaObjectRef_converion(char,byte)
|
||||
define_javaObjectRef_converion(float,float)
|
||||
define_javaObjectRef_converion(double,double)
|
||||
|
||||
#endif
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <typename T> class array_view;
|
||||
|
||||
#define JAVA_ARRAY_CLASS_SPEC(ctype, type, Type) \
|
||||
template <> class array_view<ctype> : public array_view_base<ctype> \
|
||||
{ \
|
||||
public: \
|
||||
~array_view() { clear(); } \
|
||||
array_view() {} \
|
||||
array_view(const array<ctype>& arr, bool might_be_modified_=true){reset(JNI_GetEnv(),arr,might_be_modified_);} \
|
||||
void reset(JNIEnv* jenv_, j##type##Array arr, bool might_be_modified_) { \
|
||||
clear(); \
|
||||
jenv = jenv_; \
|
||||
oldArr = arr; \
|
||||
if (arr) { \
|
||||
pdata = (ctype*)jenv->Get##Type##ArrayElements(arr, 0); \
|
||||
sz = jenv->GetArrayLength(arr); \
|
||||
} \
|
||||
might_be_modified = might_be_modified_; \
|
||||
} \
|
||||
private: \
|
||||
void clear() { \
|
||||
if (pdata) { \
|
||||
jenv->Release##Type##ArrayElements(oldArr, (j##type*)pdata, might_be_modified?0:JNI_ABORT); \
|
||||
pdata = nullptr; \
|
||||
sz = 0; \
|
||||
} \
|
||||
} \
|
||||
JNIEnv* jenv = nullptr; \
|
||||
j##type##Array oldArr; \
|
||||
bool might_be_modified; \
|
||||
};
|
||||
|
||||
JAVA_ARRAY_CLASS_SPEC(int16_t,short, Short)
|
||||
JAVA_ARRAY_CLASS_SPEC(int32_t,int, Int)
|
||||
JAVA_ARRAY_CLASS_SPEC(int64_t,long, Long)
|
||||
JAVA_ARRAY_CLASS_SPEC(char,byte, Byte)
|
||||
JAVA_ARRAY_CLASS_SPEC(float,float, Float)
|
||||
JAVA_ARRAY_CLASS_SPEC(double,double, Double)
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
template <typename T, typename JARR>
|
||||
class array_view_crit_base
|
||||
{
|
||||
public:
|
||||
array_view_crit_base() = default;
|
||||
|
||||
size_t size() const { return sz; }
|
||||
T* data() { return pdata; }
|
||||
const T* data() const { return pdata; }
|
||||
|
||||
T* begin() { return pdata; }
|
||||
T* end() { return pdata+sz; }
|
||||
const T* begin() const { return pdata; }
|
||||
const T* end() const { return pdata+sz; }
|
||||
T& operator[](size_t i) { return pdata[i]; }
|
||||
const T& operator[](size_t i) const { return pdata[i]; }
|
||||
|
||||
~array_view_crit_base() { clear(); }
|
||||
|
||||
void reset(JNIEnv* jenv_, JARR arr, bool might_be_modified_)
|
||||
{
|
||||
clear();
|
||||
jenv = jenv_;
|
||||
oldArr = arr;
|
||||
if (arr)
|
||||
{
|
||||
pdata = (T*)jenv->GetPrimitiveArrayCritical(arr, 0);
|
||||
sz = jenv->GetArrayLength(arr);
|
||||
}
|
||||
might_be_modified = might_be_modified_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void clear()
|
||||
{
|
||||
if (pdata) {
|
||||
jenv->ReleasePrimitiveArrayCritical(oldArr, pdata, might_be_modified?0:JNI_ABORT);
|
||||
pdata = nullptr;
|
||||
sz = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// this object is non-copyable
|
||||
array_view_crit_base(const array_view_crit_base&);
|
||||
array_view_crit_base& operator=(const array_view_crit_base&);
|
||||
|
||||
T* pdata = nullptr;
|
||||
size_t sz = 0;
|
||||
JNIEnv* jenv = nullptr;
|
||||
JARR oldArr;
|
||||
bool might_be_modified;
|
||||
};
|
||||
|
||||
template <typename T> class array_view_crit;
|
||||
|
||||
template <> class array_view_crit<int16_t> : public array_view_crit_base<int16_t,jshortArray> { public: array_view_crit(){} array_view_crit(const array<int16_t>& arr, bool might_be_modified_=true){reset(JNI_GetEnv(),arr,might_be_modified_);} };
|
||||
template <> class array_view_crit<int32_t> : public array_view_crit_base<int32_t,jintArray> { public: array_view_crit(){} array_view_crit(const array<int32_t>& arr, bool might_be_modified_=true){reset(JNI_GetEnv(),arr,might_be_modified_);} };
|
||||
template <> class array_view_crit<int64_t> : public array_view_crit_base<int64_t,jlongArray> { public: array_view_crit(){} array_view_crit(const array<int64_t>& arr, bool might_be_modified_=true){reset(JNI_GetEnv(),arr,might_be_modified_);} };
|
||||
template <> class array_view_crit<char> : public array_view_crit_base<char,jbyteArray> { public: array_view_crit(){} array_view_crit(const array<char>& arr, bool might_be_modified_=true){reset(JNI_GetEnv(),arr,might_be_modified_);} };
|
||||
template <> class array_view_crit<float> : public array_view_crit_base<float,jfloatArray> { public: array_view_crit(){} array_view_crit(const array<float>& arr, bool might_be_modified_=true){reset(JNI_GetEnv(),arr,might_be_modified_);} };
|
||||
template <> class array_view_crit<double> : public array_view_crit_base<double,jdoubleArray> { public: array_view_crit(){} array_view_crit(const array<double>& arr, bool might_be_modified_=true){reset(JNI_GetEnv(),arr,might_be_modified_);} };
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
// Define SWIG typemaps so SWIG will know what to do with the array_view and array_view_crit
|
||||
// objects.
|
||||
#ifdef SWIG
|
||||
%define define_array_converion(type, java_type)
|
||||
// Define array conversions for non-const arrays
|
||||
%typemap(jtype) (array_view<type>&) "java_type[]"
|
||||
%typemap(jstype) (array_view<type>&) "java_type[]"
|
||||
%typemap(jni) (array_view<type>&) tostring(j##java_type##Array)
|
||||
%typemap(javain) (array_view<type>&) "$javainput"
|
||||
%typemap(arginit) (array_view<type>&) { $1 = &temp$argnum; }
|
||||
%typemap(in) (array_view<type>&) (array_view<type> temp) { $1->reset(jenv, $input, true); }
|
||||
|
||||
%typemap(jtype) (const array_view<type>&) "java_type[]"
|
||||
%typemap(jstype) (const array_view<type>&) "java_type[]"
|
||||
%typemap(jni) (const array_view<type>&) tostring(j##java_type##Array)
|
||||
%typemap(javain) (const array_view<type>&) "$javainput"
|
||||
%typemap(arginit) (const array_view<type>&) { $1 = &temp$argnum; }
|
||||
%typemap(in) (const array_view<type>&) (array_view<type> temp) { $1->reset(jenv, $input, false); }
|
||||
%enddef
|
||||
define_array_converion(int16_t,short)
|
||||
define_array_converion(int32_t,int)
|
||||
define_array_converion(int64_t,long)
|
||||
define_array_converion(char,byte)
|
||||
define_array_converion(float,float)
|
||||
define_array_converion(double,double)
|
||||
|
||||
|
||||
|
||||
%define define_array_crit_converion(type, java_type)
|
||||
// Define array conversions for non-const arrays
|
||||
%typemap(jtype) (array_view_crit<type>&) "java_type[]"
|
||||
%typemap(jstype) (array_view_crit<type>&) "java_type[]"
|
||||
%typemap(jni) (array_view_crit<type>&) tostring(j##java_type##Array)
|
||||
%typemap(javain) (array_view_crit<type>&) "$javainput"
|
||||
%typemap(arginit) (array_view_crit<type>&) { $1 = &temp$argnum; }
|
||||
%typemap(in) (array_view_crit<type>&) (array_view_crit<type> temp) { $1->reset(jenv, $input, true); }
|
||||
|
||||
%typemap(jtype) (const array_view_crit<type>&) "java_type[]"
|
||||
%typemap(jstype) (const array_view_crit<type>&) "java_type[]"
|
||||
%typemap(jni) (const array_view_crit<type>&) tostring(j##java_type##Array)
|
||||
%typemap(javain) (const array_view_crit<type>&) "$javainput"
|
||||
%typemap(arginit) (const array_view_crit<type>&) { $1 = &temp$argnum; }
|
||||
%typemap(in) (const array_view_crit<type>&) (array_view_crit<type> temp) { $1->reset(jenv, $input, false); }
|
||||
%enddef
|
||||
define_array_crit_converion(int16_t,short)
|
||||
define_array_crit_converion(int32_t,int)
|
||||
define_array_crit_converion(int64_t,long)
|
||||
define_array_crit_converion(char,byte)
|
||||
define_array_crit_converion(float,float)
|
||||
define_array_crit_converion(double,double)
|
||||
|
||||
#endif // SWIG
|
||||
|
||||
}
|
||||
|
||||
#endif // DLIB_SWIG_JAVA_ARRAY_H_
|
||||
|
@ -1,250 +0,0 @@
|
||||
// Copyright (C) 2017 Davis E. King (davis@dlib.net)
|
||||
// License: Boost Software License See LICENSE.txt for the full license.
|
||||
#ifndef DLIB_SWIG_JVECTOR_H_
|
||||
#define DLIB_SWIG_JVECTOR_H_
|
||||
|
||||
|
||||
/*
|
||||
|
||||
This file defines two special classes, jvector and jvector_crit. Both of them have the
|
||||
interface defined by jvector_base, that is, the interface of a simple array object like
|
||||
std::vector (except without any ability to be resized). These classes are simple
|
||||
interfaces to java native arrays. So for example, suppose you had an array of int in
|
||||
java and you wanted to pass it to C++. You could create a C++ function like this:
|
||||
|
||||
void my_function(const jvector<int>& array);
|
||||
|
||||
and then within java you could call it with code like this:
|
||||
|
||||
int[] array = new int[100];
|
||||
my_function(array);
|
||||
|
||||
and it will work just like you would expect. The jvector<int> will usually result in
|
||||
the JVM doing a copy in the background. However, you can also declare your function
|
||||
like this:
|
||||
|
||||
void my_function(const jvector_crit<int>& array);
|
||||
|
||||
and still call it the same way in java, however, using jvector_crit<int> will usually
|
||||
not result in any copying, and is therefore very fast. jvector_crit uses the JNI
|
||||
routine GetPrimitiveArrayCritical() to get a lock on the java memory underlying the
|
||||
array. So it will probably prevent the garbage collector from running while your
|
||||
function is executing. The JNI documentation is somewhat vague on the limitations of
|
||||
GetPrimitiveArrayCritical(), saying only that you shouldn't hold the lock on the array
|
||||
for "an extended period" or call back into the JVM. Deciding whether or not this
|
||||
matters in your application is left as an exercise for the reader.
|
||||
|
||||
|
||||
There are two ways you can declare your methods. Taking a const reference or a
|
||||
non-const reference. E.g.:
|
||||
void my_function(const jvector<int>& array);
|
||||
void my_function(jvector<int>& array);
|
||||
The non-const version allows you to modify the contents of the array and the
|
||||
modifications will be visible to java, as you would expect.
|
||||
|
||||
You can also of course use functions taking many arguments, as is normally the case
|
||||
with SWIG. Finally, jvector works with the following primitive types:
|
||||
- int16_t
|
||||
- int32_t
|
||||
- int64_t
|
||||
- char (corresponding to java byte)
|
||||
- float
|
||||
- double
|
||||
*/
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <typename T>
|
||||
class jvector_base
|
||||
{
|
||||
public:
|
||||
jvector_base() = default;
|
||||
|
||||
size_t size() const { return sz; }
|
||||
T* data() { return pdata; }
|
||||
const T* data() const { return pdata; }
|
||||
|
||||
T* begin() { return pdata; }
|
||||
T* end() { return pdata+sz; }
|
||||
const T* begin() const { return pdata; }
|
||||
const T* end() const { return pdata+sz; }
|
||||
|
||||
T& operator[](size_t i) { return pdata[i]; }
|
||||
const T& operator[](size_t i) const { return pdata[i]; }
|
||||
|
||||
protected:
|
||||
T* pdata = nullptr;
|
||||
size_t sz = 0;
|
||||
|
||||
private:
|
||||
// this object is non-copyable
|
||||
jvector_base(const jvector_base&);
|
||||
jvector_base& operator=(const jvector_base&);
|
||||
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <typename T> class jvector;
|
||||
|
||||
#define JVECTOR_CLASS_SPEC(ctype, type, Type) \
|
||||
template <> class jvector<ctype> : public jvector_base<ctype> \
|
||||
{ \
|
||||
public: \
|
||||
~jvector() { clear(); } \
|
||||
void reset(JNIEnv* jenv_, j##type##Array arr, bool mightBeModified_) { \
|
||||
clear(); \
|
||||
jenv = jenv_; \
|
||||
oldArr = arr; \
|
||||
pdata = (ctype*)jenv->Get##Type##ArrayElements(arr, 0); \
|
||||
sz = jenv->GetArrayLength(arr); \
|
||||
mightBeModified = mightBeModified_; \
|
||||
} \
|
||||
private: \
|
||||
void clear() { \
|
||||
if (pdata) { \
|
||||
jenv->Release##Type##ArrayElements(oldArr, (j##type*)pdata, mightBeModified?0:JNI_ABORT); \
|
||||
pdata = nullptr; \
|
||||
} \
|
||||
} \
|
||||
JNIEnv* jenv = nullptr; \
|
||||
j##type##Array oldArr; \
|
||||
bool mightBeModified; \
|
||||
};
|
||||
|
||||
JVECTOR_CLASS_SPEC(int16_t,short, Short)
|
||||
JVECTOR_CLASS_SPEC(int32_t,int, Int)
|
||||
JVECTOR_CLASS_SPEC(int64_t,long, Long)
|
||||
JVECTOR_CLASS_SPEC(char,byte, Byte)
|
||||
JVECTOR_CLASS_SPEC(float,float, Float)
|
||||
JVECTOR_CLASS_SPEC(double,double, Double)
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <typename T, typename JARR>
|
||||
class jvector_crit_base
|
||||
{
|
||||
public:
|
||||
jvector_crit_base() = default;
|
||||
|
||||
size_t size() const { return sz; }
|
||||
T* data() { return pdata; }
|
||||
const T* data() const { return pdata; }
|
||||
|
||||
T* begin() { return pdata; }
|
||||
T* end() { return pdata+sz; }
|
||||
const T* begin() const { return pdata; }
|
||||
const T* end() const { return pdata+sz; }
|
||||
T& operator[](size_t i) { return pdata[i]; }
|
||||
const T& operator[](size_t i) const { return pdata[i]; }
|
||||
|
||||
~jvector_crit_base() { clear(); }
|
||||
|
||||
void reset(JNIEnv* jenv_, JARR arr, bool mightBeModified_)
|
||||
{
|
||||
clear();
|
||||
jenv = jenv_;
|
||||
oldArr = arr;
|
||||
pdata = (T*)jenv->GetPrimitiveArrayCritical(arr, 0);
|
||||
sz = jenv->GetArrayLength(arr);
|
||||
mightBeModified = mightBeModified_;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void clear()
|
||||
{
|
||||
if (pdata) {
|
||||
jenv->ReleasePrimitiveArrayCritical(oldArr, pdata, mightBeModified?0:JNI_ABORT);
|
||||
pdata = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// this object is non-copyable
|
||||
jvector_crit_base(const jvector_crit_base&);
|
||||
jvector_crit_base& operator=(const jvector_crit_base&);
|
||||
|
||||
T* pdata = nullptr;
|
||||
size_t sz = 0;
|
||||
JNIEnv* jenv = nullptr;
|
||||
JARR oldArr;
|
||||
bool mightBeModified;
|
||||
};
|
||||
|
||||
template <typename T> class jvector_crit;
|
||||
|
||||
template <> class jvector_crit<int16_t> : public jvector_crit_base<int16_t,jshortArray> {};
|
||||
template <> class jvector_crit<int32_t> : public jvector_crit_base<int32_t,jintArray> {};
|
||||
template <> class jvector_crit<int64_t> : public jvector_crit_base<int64_t,jlongArray> {};
|
||||
template <> class jvector_crit<char> : public jvector_crit_base<char,jbyteArray> {};
|
||||
template <> class jvector_crit<float> : public jvector_crit_base<float,jfloatArray> {};
|
||||
template <> class jvector_crit<double> : public jvector_crit_base<double,jdoubleArray> {};
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
// Define SWIG typemaps so SWIG will know what to do with the jvector and jvector_crit
|
||||
// objects.
|
||||
#ifdef SWIG
|
||||
%define tostring(token)
|
||||
#token
|
||||
%enddef
|
||||
|
||||
%define define_jvector_converion(type, java_type)
|
||||
// Define array conversions for non-const arrays
|
||||
%typemap(jtype) (jvector<type>&) "java_type[]"
|
||||
%typemap(jstype) (jvector<type>&) "java_type[]"
|
||||
%typemap(jni) (jvector<type>&) tostring(j##java_type##Array)
|
||||
%typemap(javain) (jvector<type>&) "$javainput"
|
||||
%typemap(arginit) (jvector<type>&) { $1 = &temp$argnum; }
|
||||
%typemap(in) (jvector<type>&) (jvector<type> temp) { $1->reset(jenv, $input, true); }
|
||||
|
||||
%typemap(jtype) (const jvector<type>&) "java_type[]"
|
||||
%typemap(jstype) (const jvector<type>&) "java_type[]"
|
||||
%typemap(jni) (const jvector<type>&) tostring(j##java_type##Array)
|
||||
%typemap(javain) (const jvector<type>&) "$javainput"
|
||||
%typemap(arginit) (const jvector<type>&) { $1 = &temp$argnum; }
|
||||
%typemap(in) (const jvector<type>&) (jvector<type> temp) { $1->reset(jenv, $input, false); }
|
||||
%enddef
|
||||
define_jvector_converion(int16_t,short)
|
||||
define_jvector_converion(int32_t,int)
|
||||
define_jvector_converion(int64_t,long)
|
||||
define_jvector_converion(char,byte)
|
||||
define_jvector_converion(float,float)
|
||||
define_jvector_converion(double,double)
|
||||
|
||||
|
||||
|
||||
%define define_jvector_crit_converion(type, java_type)
|
||||
// Define array conversions for non-const arrays
|
||||
%typemap(jtype) (jvector_crit<type>&) "java_type[]"
|
||||
%typemap(jstype) (jvector_crit<type>&) "java_type[]"
|
||||
%typemap(jni) (jvector_crit<type>&) tostring(j##java_type##Array)
|
||||
%typemap(javain) (jvector_crit<type>&) "$javainput"
|
||||
%typemap(arginit) (jvector_crit<type>&) { $1 = &temp$argnum; }
|
||||
%typemap(in) (jvector_crit<type>&) (jvector_crit<type> temp) { $1->reset(jenv, $input, true); }
|
||||
|
||||
%typemap(jtype) (const jvector_crit<type>&) "java_type[]"
|
||||
%typemap(jstype) (const jvector_crit<type>&) "java_type[]"
|
||||
%typemap(jni) (const jvector_crit<type>&) tostring(j##java_type##Array)
|
||||
%typemap(javain) (const jvector_crit<type>&) "$javainput"
|
||||
%typemap(arginit) (const jvector_crit<type>&) { $1 = &temp$argnum; }
|
||||
%typemap(in) (const jvector_crit<type>&) (jvector_crit<type> temp) { $1->reset(jenv, $input, false); }
|
||||
%enddef
|
||||
define_jvector_crit_converion(int16_t,short)
|
||||
define_jvector_crit_converion(int32_t,int)
|
||||
define_jvector_crit_converion(int64_t,long)
|
||||
define_jvector_crit_converion(char,byte)
|
||||
define_jvector_crit_converion(float,float)
|
||||
define_jvector_crit_converion(double,double)
|
||||
|
||||
#endif // SWIG
|
||||
|
||||
#endif // DLIB_SWIG_JVECTOR_H_
|
||||
|
@ -1,30 +1,32 @@
|
||||
#ifndef EXAMPLE_SWIG_ApI_H_
|
||||
#define EXAMPLE_SWIG_ApI_H_
|
||||
|
||||
// This file is essentially a small unit test for the swig cmake scripts and the jvector
|
||||
// This file is essentially a small unit test for the swig cmake scripts and the java array
|
||||
// classes. All it does it define a few simple functions for writing to and summing
|
||||
// arrays. The swig_test.java file then calls these C++ functions and checks if they work
|
||||
// correctly.
|
||||
|
||||
|
||||
|
||||
// Let's use the jvector, a tool for efficiently binding java native arrays to C++ function
|
||||
// arguments. You do this by putting this pair of include statements in your swig_api.h
|
||||
// file. Then after that you can use the jvector and jvector_crit classes.
|
||||
#include "jvector.h"
|
||||
// Let's use java_array.h, a tool for efficiently binding java native arrays to C++
|
||||
// function arguments. You do this by putting this pair of include statements in your
|
||||
// swig_api.h file. Then after that you can use the java::array, java::array_view, and
|
||||
// java::array_view_crit classes.
|
||||
#include "java_array.h"
|
||||
#ifdef SWIG
|
||||
%include "jvector.h"
|
||||
%include "java_array.h"
|
||||
#endif
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
using namespace java;
|
||||
|
||||
|
||||
// SWIG can't expose templated functions to java. We declare these here as helper
|
||||
// functions to make the non-templated routines swig will expose easier to write. You can
|
||||
// see these java exposed methods below (i.e. sum(), sum_crit(), assign(), and
|
||||
// assign_crit()).
|
||||
template <typename T>
|
||||
T tsum(const jvector_crit<T>& arr)
|
||||
T tsum(const array_view_crit<T>& arr)
|
||||
{
|
||||
T s = 0;
|
||||
for (auto& v : arr)
|
||||
@ -32,7 +34,7 @@ T tsum(const jvector_crit<T>& arr)
|
||||
return s;
|
||||
}
|
||||
template <typename T>
|
||||
T tsum(const jvector<T>& arr)
|
||||
T tsum(const array_view<T>& arr)
|
||||
{
|
||||
T s = 0;
|
||||
for (auto& v : arr)
|
||||
@ -56,41 +58,64 @@ void tassign(T& arr)
|
||||
// "global", which is where these sum and assign routines will appear. You can see
|
||||
// examples of java code that calls them in swig_test.java.
|
||||
|
||||
inline int sum_crit(const jvector_crit<int16_t>& arr) { return tsum(arr); }
|
||||
inline int sum(const jvector<int16_t>& arr) { return tsum(arr); }
|
||||
inline void assign_crit(jvector_crit<int16_t>& arr) { tassign(arr); }
|
||||
inline void assign(jvector<int16_t>& arr) { tassign(arr); }
|
||||
inline int sum_crit(const array_view_crit<int16_t>& arr) { return tsum(arr); }
|
||||
inline int sum(const array_view<int16_t>& arr) { return tsum(arr); }
|
||||
inline void assign_crit(array_view_crit<int16_t>& arr) { tassign(arr); }
|
||||
inline void assign(array_view<int16_t>& arr) { tassign(arr); }
|
||||
|
||||
|
||||
inline int sum_crit(const jvector_crit<int32_t>& arr) { return tsum(arr); }
|
||||
inline int sum(const jvector<int32_t>& arr) { return tsum(arr); }
|
||||
inline void assign_crit(jvector_crit<int32_t>& arr) { tassign(arr); }
|
||||
inline void assign(jvector<int32_t>& arr) { tassign(arr); }
|
||||
inline int sum_crit(const array_view_crit<int32_t>& arr) { return tsum(arr); }
|
||||
inline int sum(const array_view<int32_t>& arr) { return tsum(arr); }
|
||||
inline void assign_crit(array_view_crit<int32_t>& arr) { tassign(arr); }
|
||||
inline void assign(array_view<int32_t>& arr) { tassign(arr); }
|
||||
|
||||
|
||||
inline int sum_crit(const jvector_crit<int64_t>& arr) { return tsum(arr); }
|
||||
inline int sum(const jvector<int64_t>& arr) { return tsum(arr); }
|
||||
inline void assign_crit(jvector_crit<int64_t>& arr) { tassign(arr); }
|
||||
inline void assign(jvector<int64_t>& arr) { tassign(arr); }
|
||||
inline int sum_crit(const array_view_crit<int64_t>& arr) { return tsum(arr); }
|
||||
inline int sum(const array_view<int64_t>& arr) { return tsum(arr); }
|
||||
inline void assign_crit(array_view_crit<int64_t>& arr) { tassign(arr); }
|
||||
inline void assign(array_view<int64_t>& arr) { tassign(arr); }
|
||||
|
||||
|
||||
inline int sum_crit(const jvector_crit<char>& arr) { return tsum(arr); }
|
||||
inline int sum(const jvector<char>& arr) { return tsum(arr); }
|
||||
inline void assign_crit(jvector_crit<char>& arr) { tassign(arr); }
|
||||
inline void assign(jvector<char>& arr) { tassign(arr); }
|
||||
inline int sum_crit(const array_view_crit<char>& arr) { return tsum(arr); }
|
||||
inline int sum(const array_view<char>& arr) { return tsum(arr); }
|
||||
inline void assign_crit(array_view_crit<char>& arr) { tassign(arr); }
|
||||
inline void assign(array_view<char>& arr) { tassign(arr); }
|
||||
|
||||
|
||||
|
||||
inline double sum_crit(const jvector_crit<double>& arr) { return tsum(arr); }
|
||||
inline double sum(const jvector<double>& arr) { return tsum(arr); }
|
||||
inline void assign_crit(jvector_crit<double>& arr) { tassign(arr); }
|
||||
inline void assign(jvector<double>& arr) { tassign(arr); }
|
||||
inline double sum_crit(const array_view_crit<double>& arr) { return tsum(arr); }
|
||||
inline double sum(const array_view<double>& arr) { return tsum(arr); }
|
||||
inline void assign_crit(array_view_crit<double>& arr) { tassign(arr); }
|
||||
inline void assign(array_view<double>& arr) { tassign(arr); }
|
||||
|
||||
|
||||
inline float sum_crit(const jvector_crit<float>& arr) { return tsum(arr); }
|
||||
inline float sum(const jvector<float>& arr) { return tsum(arr); }
|
||||
inline void assign_crit(jvector_crit<float>& arr) { tassign(arr); }
|
||||
inline void assign(jvector<float>& arr) { tassign(arr); }
|
||||
inline float sum_crit(array<float> arr)
|
||||
{
|
||||
array_view_crit<float> a(arr);
|
||||
return tsum(a);
|
||||
}
|
||||
inline float sum(const array<float>& arr)
|
||||
{
|
||||
array_view<float> a(arr);
|
||||
return tsum(a);
|
||||
}
|
||||
inline void assign_crit(array_view_crit<float>& arr) { tassign(arr); }
|
||||
inline void assign(array<float>& arr)
|
||||
{
|
||||
array_view<float> a(arr);
|
||||
tassign(a);
|
||||
}
|
||||
|
||||
array<int32_t> make_an_array(size_t s)
|
||||
{
|
||||
array<int32_t> arr(s);
|
||||
array_view_crit<int32_t> a(arr);
|
||||
|
||||
for (size_t i = 0; i < a.size(); ++i)
|
||||
a[i] = i;
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
@ -69,6 +69,14 @@ public class swig_test
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertIsEqual(int val1, int val2)
|
||||
{
|
||||
if (val1 != val2)
|
||||
{
|
||||
throw new RuntimeException("Test failed " + val1 + " should be equal to " + val2);
|
||||
}
|
||||
}
|
||||
|
||||
public static double sum(double[] arr)
|
||||
{
|
||||
double s = 0;
|
||||
@ -233,6 +241,13 @@ public class swig_test
|
||||
assertIs28(global.sum_crit(arr));
|
||||
}
|
||||
}
|
||||
{
|
||||
int[] a = global.make_an_array(4);
|
||||
for (int i = 0; i < a.length; ++i)
|
||||
{
|
||||
assertIsEqual(a[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("\n\n ALL TESTS COMPLETED SUCCESSFULLY\n");
|
||||
}
|
||||
|
@ -424,7 +424,7 @@ namespace dlib
|
||||
template <typename T>
|
||||
int get_ld (const matrix_op<op_pointer_to_col_vect<T> >& m) { return m.nc(); }
|
||||
template <typename T>
|
||||
int get_ld (const matrix_op<op_pointer_to_mat<T> >& m) { return m.nc(); }
|
||||
int get_ld (const matrix_op<op_pointer_to_mat<T> >& m) { return m.op.stride; }
|
||||
|
||||
// --------
|
||||
|
||||
@ -443,7 +443,7 @@ namespace dlib
|
||||
template <typename T>
|
||||
int get_inc (const matrix_op<op_pointer_to_col_vect<T> >& ) { return 1; }
|
||||
template <typename T>
|
||||
int get_inc (const matrix_op<op_pointer_to_mat<T> >& ) { return 1; }
|
||||
int get_inc (const matrix_op<op_pointer_to_mat<T> >& m) { return m.op.stride==m.op.cols ? 1 : 0; }
|
||||
|
||||
template <typename T, long NR, long NC, typename MM, typename L>
|
||||
int get_inc (const matrix<T,NR,NC,MM,L>& ) { return 1; }
|
||||
|
@ -319,11 +319,19 @@ namespace dlib
|
||||
const T* ptr_,
|
||||
const long nr_,
|
||||
const long nc_
|
||||
) : ptr(ptr_), rows(nr_), cols(nc_){}
|
||||
) : ptr(ptr_), rows(nr_), cols(nc_), stride(nc_){}
|
||||
|
||||
op_pointer_to_mat(
|
||||
const T* ptr_,
|
||||
const long nr_,
|
||||
const long nc_,
|
||||
const long stride_
|
||||
) : ptr(ptr_), rows(nr_), cols(nc_), stride(stride_){}
|
||||
|
||||
const T* ptr;
|
||||
const long rows;
|
||||
const long cols;
|
||||
const long stride;
|
||||
|
||||
const static long cost = 1;
|
||||
const static long NR = 0;
|
||||
@ -333,7 +341,7 @@ namespace dlib
|
||||
typedef default_memory_manager mem_manager_type;
|
||||
typedef row_major_layout layout_type;
|
||||
|
||||
const_ret_type apply (long r, long c) const { return ptr[r*cols + c]; }
|
||||
const_ret_type apply (long r, long c) const { return ptr[r*stride + c]; }
|
||||
|
||||
long nr () const { return rows; }
|
||||
long nc () const { return cols; }
|
||||
@ -419,6 +427,27 @@ namespace dlib
|
||||
return matrix_op<op>(op(ptr,nr,nc));
|
||||
}
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
const matrix_op<op_pointer_to_mat<T> > mat (
|
||||
const T* ptr,
|
||||
long nr,
|
||||
long nc,
|
||||
long stride
|
||||
)
|
||||
{
|
||||
DLIB_ASSERT(nr >= 0 && nc >= 0 && stride > 0 ,
|
||||
"\tconst matrix_exp mat(ptr, nr, nc, stride)"
|
||||
<< "\n\t nr and nc must be >= 0 while stride > 0"
|
||||
<< "\n\t nr: " << nr
|
||||
<< "\n\t nc: " << nc
|
||||
<< "\n\t stride: " << stride
|
||||
);
|
||||
typedef op_pointer_to_mat<T> op;
|
||||
return matrix_op<op>(op(ptr,nr,nc,stride));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
}
|
||||
|
@ -153,6 +153,35 @@ namespace dlib
|
||||
the pointer and thus will not delete or free it.
|
||||
!*/
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
typename T
|
||||
>
|
||||
const matrix_exp mat (
|
||||
const T* ptr,
|
||||
long nr,
|
||||
long nc,
|
||||
long stride
|
||||
);
|
||||
/*!
|
||||
requires
|
||||
- nr >= 0
|
||||
- nc >= 0
|
||||
- stride > 0
|
||||
- ptr == a pointer to at least (nr-1)*stride+nc T objects (or the NULL pointer if nr*nc==0)
|
||||
ensures
|
||||
- returns a matrix M such that:
|
||||
- M.nr() == nr
|
||||
- m.nc() == nc
|
||||
- for all valid r and c:
|
||||
M(r,c) == ptr[r*stride + c]
|
||||
(i.e. the pointer is interpreted as a matrix laid out in memory
|
||||
in row major order, with a row stride of the given stride amount.)
|
||||
- Note that the returned matrix doesn't take "ownership" of
|
||||
the pointer and thus will not delete or free it.
|
||||
!*/
|
||||
|
||||
// ----------------------------------------------------------------------------------------
|
||||
|
||||
template <
|
||||
|
@ -870,7 +870,7 @@ namespace
|
||||
conv2.get_gradient_for_filters(true, gi, data, filter_gradient2);
|
||||
|
||||
dlog << LINFO << "filter gradient error: "<< max(abs(mat(filter_gradient1)-mat(filter_gradient2)));
|
||||
DLIB_TEST_MSG(max(abs(mat(filter_gradient1)-mat(filter_gradient2))) < 1e-3, max(abs(mat(filter_gradient1)-mat(filter_gradient2))));
|
||||
DLIB_TEST_MSG(max(abs(mat(filter_gradient1)-mat(filter_gradient2))) < 2e-3, max(abs(mat(filter_gradient1)-mat(filter_gradient2))));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1350,6 +1350,21 @@ namespace
|
||||
DLIB_TEST(mm(3) == 4);
|
||||
}
|
||||
|
||||
{
|
||||
const long n = 5;
|
||||
matrix<double> m1, m2, m3, truth;
|
||||
m1 = randm(n,n);
|
||||
m2 = randm(n,n);
|
||||
|
||||
rectangle rect1(1,1,3,3);
|
||||
rectangle rect2(2,1,4,3);
|
||||
|
||||
truth = subm(m1,rect1)*subm(m2,rect2);
|
||||
m3 = mat(&m1(0,0)+6, 3,3, m1.nc()) * mat(&m2(0,0)+7, 3,3, m2.nc());
|
||||
|
||||
DLIB_TEST(max(abs(truth-m3)) < 1e-13);
|
||||
}
|
||||
|
||||
{
|
||||
const long n = 5;
|
||||
matrix<double> m1, m2, m3, truth;
|
||||
|
Loading…
Reference in New Issue
Block a user