- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试通过 JNI 从在 C++ 类中创建的 pthread
回调。使用以下代码。我可以从我的 Android 应用程序触发按钮按下,我的 callbackStringJNI()
工作正常。 pthread
的创建是由通过 JNI 向下传递的按钮按下触发的。如果 pthread
创建的函数/线程尝试异步调用 callbackStringJNI()
,我会在 Android 应用 messageMe()
中获取传递的字符串>(仅在调试器中断时查看),但如果我尝试使用字符串(IE,在 UI 上显示某些内容),应用程序会在 Android 源“Handler.class”函数 joinThreadPool
上中断,然后如果我再次恢复,我会在下面的 Android 代码中遇到“异常”:
Android API 错误代码:
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(//////////Hits here - this message is never actually displayed though.
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
我可以将字符串复制到另一个变量,如 messageMe()
中所示,但我仍然不能在 Toast
甚至 中使用该字符串> TextView
。我现在很困惑为什么我不能从 pthread
回调,欢迎提出任何建议。
安卓Java:
package com.example.somecontrol1;
public class MainActivity extends Activity {
// load the library - name matches jni/Android.mk
static {
System.loadLibrary("ndkfoo");
}
private native String inintNativeClass();
private native String SetUpSocketNC();
private native void initJNICallback();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initJNICallback();
inintNativeClass();
public void messageMe(String text) {
String teststr = text;
Toast.makeText(getApplicationContext(), teststr, Toast.LENGTH_LONG).show();
//appendTextAndScroll(text, gtv);
}
}
在下面的代码中,当 getJNIEnv()
被调用并且执行来自按下按钮时,JNI_OK
就是结果。当调用来自 pthread 中的回调时,JNI_EDETACHED
是结果并且 AttachCurrentThread()
成功。
JNI C ndkfoo.c
#include <jni.h>
#include "testSocketClassWrapper.hpp"
static JavaVM* cachedJVM;
static jobject g_javaObj;
static jclass cachedclassID;
void *m_GBLpmyCSocket = NULL;
jint JNI_OnLoad(JavaVM *jvm, void *reserved)
{
cachedJVM = jvm;
JNIEnv* env;
if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4) != JNI_OK) {
LOGD("GETENVFAILEDONLOAD");
return -1;
}
return JNI_VERSION_1_4;
}
void Java_com_example_somecontrol1_MainActivity_initJNICallback(JNIEnv* env, jobject jobj) {
//LOGD("Java_org_test_games_Wrapper_initJNIBridge()");
g_javaObj = (*env)->NewGlobalRef(env, jobj);
jclass storeclassID = (*env)->FindClass(env, "com/example/somecontrol1/MainActivity");
if ( (*env)->ExceptionCheck(env) == JNI_TRUE ){
(*env)->ExceptionDescribe(env);
LOGD("got into exception describe");
}
cachedclassID = (jclass)(*env)->NewGlobalRef(env, storeclassID);
if ( (*env)->ExceptionCheck(env) == JNI_TRUE ){
(*env)->ExceptionDescribe(env);
LOGD("got into exception describe");
}
}
jstring Java_com_example_somecontrol1_MainActivity_inintNativeClass(JNIEnv * env, jobject object){
m_GBLpmyCSocket = (void *)MyClass_create();
return (*env)->NewStringUTF(env, "launched class");
}
typedef struct JniMethodInfo_
{
JNIEnv* env;
jclass classID;
jmethodID methodID;
} JniMethodInfo;
static JNIEnv* getJNIEnv()//was JNIEnv
{
//JavaVM* jvm = cocos2d::JniHelper::getJavaVM();
if (NULL == cachedJVM) {
LOGD("Failed to get JNIEnv. JniHelper::getJavaVM() is NULL");
return NULL;
}
JNIEnv *env = NULL;
// get jni environment
jint ret = (*cachedJVM)->GetEnv(cachedJVM, (void**)&env, JNI_VERSION_1_4);
switch (ret) {
case JNI_OK :
// Success!
LOGD("getenv successA");
return env;
case JNI_EDETACHED :
// Thread not attached
LOGD("thread not attached");
// TODO : If calling AttachCurrentThread() on a native thread
// must call DetachCurrentThread() in future.
// see: http://developer.android.com/guide/practices/design/jni.html
if ((*cachedJVM)->AttachCurrentThread(cachedJVM, &env, NULL) < 0)
{
LOGD("Failed to get the environment using AttachCurrentThread()");
return NULL;
} else {
// Success : Attached and obtained JNIEnv!
LOGD("getenv successB");
return env;
}
case JNI_EVERSION :
// Cannot recover from this error
LOGD("JNI interface version 1.4 not supported");
default :
LOGD("Failed to get the environment using GetEnv()");
return NULL;
}
}
static bool getMethodInfo(JniMethodInfo *methodinfo, const char *methodName, const char *paramCode)
{
jmethodID methodID = 0;
JNIEnv *pEnv = 0;
bool bRet = false;
do
{
pEnv = getJNIEnv();
if (! pEnv)
{
LOGD("getJNIEnv Break Called");
break;
}
//jclass classID = getClassID(pEnv);
//jclass classID = cachedclassID;
//methodID = (*pEnv)->GetMethodID(pEnv, classID, methodName, paramCode);
methodID = (*pEnv)->GetMethodID(pEnv, cachedclassID, methodName, paramCode);
if (! methodID)
{
LOGD("Failed to find method id of %s", methodName);
break;
}
//methodinfo->classID = classID;
methodinfo->env = pEnv;
methodinfo->methodID = methodID;
bRet = true;
} while (0);
return bRet;
}
void callbackStringJNI(const char *newstr)
{
LOGD("callbackStringJNI");
JniMethodInfo methodInfo;
if (! getMethodInfo(&methodInfo, "messageMe", "(Ljava/lang/String;)V"))
{
LOGD("Cannot find method!");
return;
}
jstring jstr = (*methodInfo.env)->NewStringUTF(methodInfo.env, newstr);
(*methodInfo.env)->CallVoidMethod(methodInfo.env, g_javaObj, methodInfo.methodID, jstr);
}
类包装器
//file testSocketClassWrapper.cpp
#include "testSocketClassWrapper.hpp"
#include "testSocketClass.hpp"
extern "C" void* MyClass_create() {
return new mYNewClass;
}
extern "C" void MyClass_release(void* myclass) {
delete static_cast<mYNewClass*>(myclass);
}
extern "C" void MyClass_sendCommandToSerialDevice(void* myclass, int cmd, int params, int id) {
static_cast<mYNewClass*>(myclass)->sendCommandToSerialDevice(cmd,params,id);
}
extern "C" void SetUpSocket(void* myclass, int cmd, int params, int id) {
static_cast<mYNewClass*>(myclass)->SetUpSocket(cmd,params,id);
}
extern "C" void Startcntl(void* myclass, int cmd, int params, int id) {
static_cast<mYNewClass*>(myclass)->Startcntl();
}
extern "C" void Stopcntl(void* myclass, int cmd, int params, int id) {
static_cast<mYNewClass*>(myclass)->Stopcntl();
}
C++ 类
//file testSocketClass.cpp
void mYNewClass::SetUpSocket(int Command, int Parameters, int DeviceID){
thread1 = 0;
iret1 = 0;
iret1 = pthread_create( &thread1, NULL, &mYNewClass::thread_helper, this);
}
void mYNewClass::Startcntl(){
callbackStringJNI("sent start");//////this works.
}
C++ 头文件
//file testSocketClass.hpp
extern "C" {
void callbackStringJNI(const char *);
}
class mYNewClass{
public:
void *threadfunc(void)
{
LOGD("in thread");
while(1){
LOGD("thread looping");
callbackStringJNI("readata start");
LOGD("sleep");
sleep(30);
}
LOGD("after callbackStringJNI");////this does not work
return(0);
}
static void *thread_helper(void *context)
{
return ((mYNewClass *)context)->threadfunc();
}
最佳答案
找到解决方案,深入了解根本原因将不胜感激。
显然回调正在使用 Android 工作线程,无法访问 UI 线程。
修复 Android java 类 messageMe
函数。
public void messageMe(final String text) {
runOnUiThread(new Runnable() {
public void run()
{
Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT).show();
}
});
}
我确实做了另一项更改,更多的是为了减少开销。我像这样在 initJNICallback
中缓存了 methodID。
static jmethodID cachedmethodID;
initJNICallback(){
cachedmethodID = (*env)->GetMethodID(env, storeclassID, "messageMe", "(Ljava/lang/String;)V");//no NewGlobalRef needed.
}
关于java - 通过 JNI 从 pthread 回调失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19848648/
我正在将一些 pthreads 代码添加到我使用 autotools 构建的 Linux 应用程序中。我收到关于未在 libpthreads 中链接的错误。所以我想在 autotools 中指定 pt
libpthread 库位于 Linux 系统的哪个目录中? 最佳答案 有多种方法可以找出这一点。 只需输入 find / -name 'libpthread.so' -print找到名为 libpt
pthread 属性对象是否需要在使用它们的对象的生命周期内存在,或者在使用它们后立即销毁它们是否安全?例如: // Create the mutex attributes. pthread_mute
到目前为止我读过的所有文档似乎都表明我的 vxWorks (6.8) 版本中存在 posix 线程支持,但是一个简单的测试应用程序无法按预期执行。来源如下: tTest.h #include cla
我试图找到指定 pthreads 标准的文档。我见过各种指向 IEEE 1003.1c-1995 的链接(即 Wikipedia 或 OpenGroup )。然而,当我在 IEEE 标准站点上搜索此文
我试图找到指定 pthreads 标准的文档。我见过各种指向 IEEE 1003.1c-1995 的链接(即 Wikipedia 或 OpenGroup )。然而,当我在 IEEE 标准站点上搜索此文
我在 MSVC 2010 上运行一个 pthread,我已经包含 pthreadVC2 .lib & .dll。来自以下网站 http://sourceware.org/pthreads-win32/
我的问题是: 如何在不更改其他 pthread 中的当前目录的情况下更改 pthread 中的当前目录,我找到了一个使用 openat() 函数的解决方案,但我没有找到任何解释它如何工作的示例。 使用
是否可以通过任何方式更改进程可以创建的 pthread 数量限制? 目前在我的 linux 系统上我可以创建大约 380 个线程,但我想增加它,只要内存可用。 最佳答案 减少用户的堆栈大小' ulim
问候。我正在尝试创建一个 autoconf 配置脚本,该脚本自动检查要使用的 pthread 选项,并且理想情况下,在使用 gcc 编译时指定 -pthread。 我希望 AX_PTHREAD 能够工
如何知道 pthread 是否死亡? 有办法检查 pthread 状态吗? 最佳答案 if(pthread_kill(the_thread, 0) == 0) { /* still runni
我正在从一个由互斥锁控制的固定大小的全局池中分配我的 pthread 线程特定数据。 (有问题的代码不允许动态分配内存;它允许使用的所有内存都由调用者作为单个缓冲区提供。pthreads 可能会分配内
在阅读了一些 MPI 规范后,我了解到,当使用 MPI_THREAD_SERIALIZED 进行初始化时,程序必须确保发生在不同线程中的 MPI_Send/Recv 调用不能重叠。换句话说,您需要一个
我尝试根据 this guide 安装 pthread win32 . 我将 pthreadVC2.dll 文件添加到 C:\Windows 并将 pthreadVC2.lib 文件添加到 C:\Pr
我有一个 pthreads 程序。我必须使用 Linux 中的 gcc -pthread(-pthreads 是无法识别的选项)和 Sun 中的 gcc -pthreads(-pthread 是无法识
我有一个包含文件名列表的文件,我想在其中搜索一个词并替换它我稍微修改了代码只是为了在这里只显示相关部分问题是如果我在该列表中只有一个文件,它不会用多线程处理它,因为线程只有在我有多个文件时才工作所以我
我正在编写一个 SMT 程序,并且正在尝试解决一个有趣的问题。 我需要所有函数一起退出,但是有些线程卡在障碍物上,即使我不希望它们这样做。 我的问题是:当我删除障碍时会发生什么?卡在屏障处的线程会释放
我阅读了有关 pthread 及其相关 API 的所有内容,以创建、锁定和同步不同的线程。但我经常发现线程池、消费者/生产者等词提示。我理解这些是 pthread 实现的模型。 任何人都可以让我知道
我在 man pthread_join 中读到,多个 pthread 不能加入一个已经加入的 pthread。还有另一种方法可以达到相同的结果吗?多个 pthread 挂起自己,直到某个特定的 pth
我知道 OpenMP 实际上只是一组编译成 pthread 的宏。有没有办法在编译的其余部分发生之前查看 pthread 代码?我正在使用 GCC 进行编译。 最佳答案 首先,OpenMP 不是一组简
我是一名优秀的程序员,十分优秀!