如何从 jni 函数返回多个变量,避免数组 mangaling 的开销?
最佳答案
我可以想出三种不同的方法。
回调
从您的 JNI 代码中调用一个带有多个参数的 Java 方法,在您的 Java 代码中的某处设置一个变量,您可以在从该方法返回时检索该变量。
JNIEXPORT void JNICALL Java_my_package_name_JNIReturnExample_returnWithJavaCallback(JNIEnv *env, jobject javaThis, jfloat param1, jfloat param2)
{
// Get the class of the current calling object
jclass clazz = (*env)->GetObjectClass(env, javaThis);
// Get the method id of the instance method: void javaCallback(float, float) in my.package.name.JNIReturnExample
jmethodID callback = (*env)->GetMethodID(env, clazz, "javaCallback", "(FF)V");
// Calls my.package.name.JNIReturnExample#javaCallback(float, float);
(*env)->CallVoidMethod(env, javaThis, callback, param1, param2);
}
返回一个新的 Java 对象
在JNI中实例化一个Java对象(my.package.name.JNIReturnExample),并返回给Java。
JNIEXPORT jobject JNICALL Java_my_package_name_JNIReturnExample_returnObjectValue(JNIEnv *env, jobject javaThis, jfloat param1, jfloat param2)
{
// Get the class we wish to return an instance of
jclass clazz = (*env)->FindClass(env, "my/package/name/JNIReturnObject");
// Get the method id of an empty constructor in clazz
jmethodID constructor = (*env)->GetMethodID(env, clazz, "<init>", "()V");
// Create an instance of clazz
jobject obj = (*env)->NewObject(env, clazz, constructor);
// Get Field references
jfieldID param1Field = (*env)->GetFieldID(env, clazz, "param1", "F");
jfieldID param2Field = (*env)->GetFieldID(env, clazz, "param2", "F");
// Set fields for object
(*env)->SetFloatField(env, obj, param1Field, param1);
(*env)->SetFloatField(env, obj, param2Field, param2);
// return object
return obj;
}
传递一个 Java 对象作为参数,并设置它的字段
在您的 Java 代码中创建一个 Java 对象的新实例,并将该对象作为参数传递给您的 JNI 函数。
JNIEXPORT void JNICALL Java_my_package_name_JNIReturnExample_setObjectFields(JNIEnv *env, jobject javaThis, jobject obj, jfloat param1, jfloat param2)
{
// Get the class of the input object
jclass clazz = (*env)->GetObjectClass(env, obj);
// Get Field references
jfieldID param1Field = (*env)->GetFieldID(env, clazz, "param1", "F");
jfieldID param2Field = (*env)->GetFieldID(env, clazz, "param2", "F");
// Set fields for object
(*env)->SetFloatField(env, obj, param1Field, param1);
(*env)->SetFloatField(env, obj, param2Field, param2);
}
请注意,无论您决定使用哪种方法,都应该缓存各种 JNI 类型 jclass、jmethodID、jfieldID,因为 JNI 查找操作很慢,而且实际上只需要执行一次。
缓存
在回调方法中缓存 JNI 引用,并使用方法调用它们:
static jclass myCallbackClass;
static jmethodID myCallbackMethod;
/**
* Call this method in JNI_OnLoad
*/
void CacheCallback()
{
// Get a reference to the Callback class
jclass clazz = (*env)->FindClass(env, "my/package/name/JNIReturnExample");
// Store a global reference, since the local one will be freed when returning from the function.
myCallbackClass = (*env)->NewGlobalRef(env, clazz);
// Get a reference to the static callback method
jmethodID callback = (*env)->GetStaticMethodID(env, myCallbackClass, "jniCallback", "(II)V");
// jmethodID doesn't need a NewGlobalRef call
myCallbackMethod = callback;
}
/**
* Call this method in JNI_OnUnload
*/
void ReleaseCallback()
{
(*env)->DeleteGlobalRef(env, myCallbackClass);
myCallbackClass = NULL;
// jmethodIDs are safe to keep without an explicit global reference, for this reason, we don't need to delete the reference either.
myCallbackMethod = NULL;
}
关于java - android jni返回多个变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29043872/
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题
我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
我正在编写一个gem,我必须在其中fork两个启动两个webrick服务器的进程。我想通过基类的类方法启动这个服务器,因为应该只有这两个服务器在运行,而不是多个。在运行时,我想调用这两个服务器上的一些方法来更改变量。我的问题是,我无法通过基类的类方法访问fork的实例变量。此外,我不能在我的基类中使用线程,因为在幕后我正在使用另一个不是线程安全的库。所以我必须将每个服务器派生到它自己的进程。我用类变量试过了,比如@@server。但是当我试图通过基类访问这个变量时,它是nil。我读到在Ruby中不可能在分支之间共享类变量,对吗?那么,还有其他解决办法吗?我考虑过使用单例,但我不确定这是
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这
我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R