大佬教程收集整理的这篇文章主要介绍了通过 SWIG 在 Java 中访问 uint8_t 向量,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用 SWIG 开发 Java C++ 桥;我的c++方法如下:
std::vector<uint8_t> ArduGrabClass::grab() {
IMAGE_FORMAT fmt = { IMAGE_ENCoding_I420,100 };
BUFFER *buffer = arducam_capture(camera_instance,&fmt,352000);
return vector<uint8_t>(buffer->data,buffer->data + buffer->length);
}
即删减,真正的方法持有c++类中的缓冲区对象,以便java端可以释放它。但是,我需要在 Java 端访问这些数据,最好在 ByteBuffer 中,否则在数组中。但是我不知道该怎么做; JNI 方法 NewDirectByteBufer 似乎很合适,但 SWIG 正在处理所有 JNI 内容,所以我不知道如何告诉 SWIG 使用 NewDirectByteBufer 方法。
编写一个 typemap 来调用 NewDirectByteBuffer
是完全可行的,但正如所写的那样,这绝对不是包装代码的正确方法。所写的问题有两个方面:
ByteBuffer
指代不再有效的内存ByteBuffer
被垃圾收集时,目前没有什么可以释放该内存,因此您会泄漏内存arducam_capture
本身的调用需要以某种方式与对 arducam_release_buffer
的调用配对 - 您可以将其添加到 ArduGrabClass::grab()
函数中,但请参见下文因此,如果您想使用 std::vector
副本,我建议您只使用现有的 SWIG 支持 std::vector
,或者将其复制到某些 JNI 代码中的新数组中。如果您有兴趣,我可以演示如何做到这一点,但目前我专注于如何正确使用 ByteBuffer
和 arducam_capture
的问题。
为了有一个返回 ByteBuffer
并在之后被清理的 Java 方法,我们想安排使用一个 Cleaner 来发现 ByteBuffer
超出范围。
如果我们更改包装函数以返回 BUFFER *
而不是 std::vector
中的副本,我们可以在生成的转换内部使用一些 SWIG 支持来调用我们添加的额外函数进入我们为我们调用 NewDirectByteBuffer
的包装器。然后,在该代码中,我们还可以使用 ByteBuffer
注册 Runnable
,该 arducam_release_buffer
将为我们调用 %module test
%pragma(java) modulecode=%{
// Create a single cleaner thread for all our buffers to register with
// note package level access is deliberate
static final java.lang.ref.Cleaner cc = java.lang.ref.Cleaner.create();
static {
// actually load our shared object!
System.loadLibrary("test");
}
%}
// later on when we implement toBuffer() we need the environment pointer.
// This adds it into our method call automatically
%typemap(in,numinputs=0) JNIEnv * %{
$1 = jenv;
%}
// Our native implementation of toBuffer on BUFFER is going to return
// a ByteBuffer sTraight up for us,with no need for conversions
%typemap(jtypE) jobject toBuffer "java.nio.byteBuffer"
%typemap(jstypE) jobject toBuffer "java.nio.byteBuffer"
// When we hand the ByteBuffer off to a caller we need to register
// something to do the clean up for us. This is where we register it.
%typemap(javaout) jobject toBuffer {
java.nio.byteBuffer buf = $jnicall; // actually call the native code
System.out.println("In toBuffer"); // To prove it worked!
// Our cleaner instance lives in the module itself
$module.cc.register(buf,new Runnable(){
public void run() {
System.out.println("in buffer cleanup java side");
// We add a (privatE) cleanup function we can just call here
BUFFER.this.cleanup();
}
});
// Now it's registered actually let them have it
return buf;
}
// Every time we return a BUFFER * call toBuffer() on it instead
%typemap(javaout) BUFFER * {
return new $javaclassname($jnicall,$owner).toBuffer();
}
// Since we're going to call toBuffer() the return type is different
%typemap(jstypE) BUFFER * "java.nio.byteBuffer"
// Hide lots of thing about the BUFFER class outside our package
%typemap(javaclassmodifiers) BUFFER "class"
%javamethodmodifiers BUFFER::cleanup() "private";
%javamethodmodifiers BUFFER::toBuffer "";
// BEGIN Faked definitions,just for tesTing...
%{
typedef struct {
void *data;
int len;
} BUFFER;
typedef struct {
enum { IMAGE_ENCODING_I420 } a;
int n;
} IMAGE_FORMAT;
BUFFER * arducam_capture(void * instance,IMAGE_FORMAT *fmt,int timeout) {
(void)instance; (void)fmt; (void)timeout;
BUFFER *buf = malloc(sizeof *buf);
*buf = (BUFFER){
.data = malloc(100),.len = 100,};
return buf;
}
void arducam_release_buffer(BUFFER *instancE) {
free(instance->data);
free(instancE);
}
%}
// END TESTinG
// All the details of BUFFER are not public for Java users
%nodefaultctor BUFFER;
%nodefaultdtor BUFFER;
typedef struct {} BUFFER;
// In addition to what's really in the buffer object we want to add another
// two methods.
%extend BUFFER {
// toBuffer() is used by our internals when returning a BUFFER
jobject toBuffer(JNIEnv *jenv) const {
// Swig provides JCALLx macros for us,but they are not usable inside %extend :(
%#ifdef __cplusplus__
return jenv->NewDirectByteBuffer($self->data,$self->len);
%#else
return (*jenv)->NewDirectByteBuffer(jenv,$self->data,$self->len);
%#endif
}
// Cleanup is used when the buffer is dead
void cleanup() {
arducam_release_buffer($self);
}
}
%inline %{
// Now,wrap a modified version of your code
BUFFER *do_capture() {
void *camera_instance = NULL;
IMAGE_FORMAT fmt = { IMAGE_ENCODING_I420,100 };
BUFFER *buffer = arducam_capture(camera_instance,&fmt,352000);
return buffer;
}
%}
。
为我们执行此操作的 SWIG 接口示例是:
public class run {
public static void main(String[] argv) {
for (int i = 0; i < 100; ++i) {
java.nio.byteBuffer buf = test.do_capture();
System.gc();
}
}
}
然后尝试一下:
swig3.0 -java -Wall test.i
gcc -Wall -Wextra -o libtest.so -I/usr/lib/jvm/default-java/include/ -I/usr/lib/jvm/default-java/include/linux test_wrap.c -shared
javac *.java -Xlint:deprecation
LD_LIBRARY_PATH=. java run
In toBuffer
in buffer cleanup java side
......
然后我们可以构建和运行:
pri@R_874_11035@
以上是大佬教程为你收集整理的通过 SWIG 在 Java 中访问 uint8_t 向量全部内容,希望文章能够帮你解决通过 SWIG 在 Java 中访问 uint8_t 向量所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。