JNI和Qt通信 (Part 3)
来源:互联网 发布:单片机软件调试 编辑:程序博客网 时间:2024/04/30 18:23
Part 3
启动Qt程序
通过Java启动Qt程序可以调用命令行, 这样Qt会在另一个进程开始.
public
static
void
launchSampleApp() {
Runtime rn = Runtime.getRuntime();
Process p =
null
;
try
{
String command =
"QtAppSample"
;
p = rn.exec(command);
}
catch
(Exception e) {
System.out.println(
"JAVA Failed to launch Sample."
);
}
}
>用进程启动Qt可能在通信效率和资源共享方面有些影响.
Qt事件循环是个dead loop, 如果直接在JNI中启动Qt程序会把Java的主线程Block住; Qt main event loop will block the Java main thread;
Java 启动Qt需要另起一个线程
class
Main
{
public
static
JNISample sample =
new
JNISample();
public
static
void
main(String[] args)
{
Thread t =
new
Thread(
new
Runnable() {
public
void
run() {
sample.launchSample();
}
});
t.start();
}
}
>JNISample的launchSample()函数是一个native方法
public
native
void
launchSample();
C++方面, 可以使用static instance的方式来引用Qt类;
Qt class: 类似singleton, 可以在JNI的cpp函数实现中引用静态的Qt的类来启动Qt程序;
class
QML_EXPORT QMLSample :
public
QObject
{
Q_OBJECT
public
:
static
QMLSample * GetInstance();
private
:
QMLSample ();
private
:
QDeclarativeView* mpView;
JNIEnv* mpEnv;
static
QMLSample * mpSInstance;
};
JNI函数启动Qt程序
JNIEXPORT
void
JNICALL Java_JNISample_launchSample
(JNIEnv *env, jobject obj)
{
Q_UNUSED(obj);
int
argc = 0;
char
** argv = NULL;
QApplication app(argc, argv);
QMLSample::GetInstance()->Show();
QMLSample::GetInstance()->SetJNIEnv(env);
app.exec();
}
跨线程通信
signal/slot
Java在子线程启动了Qt, 如果Java要向Qt发送消息的话, 需要使用signal/slot的方式.
Note 如果直接使用JNI调用Qt的directly方法, e.g. setWindowTitle(), Qt会报错: "setProperty : Cannot send events to objects owned by a different thread"
除了 1)signal/slot, 还可以显式使用 2)QMetaObject::invoke(), 利用MetaObject机制调用Qt函数
Note 信号发送方式需要改为 Qt::QueuedConnection (或者使用默认的AutoConnection)
e.g,2)
const
QMetaObject* metaObj = QMLSample::GetInstance()->metaObject();
int
methodIndex = metaObj->indexOfMethod(
"FunctionName(int,QString)"
);
QMetaMethod method = metaObj->method(methodIndex);
bool
ret = method.invoke(QMLDLLSample::GetInstance(),
Qt::AutoConnection,
Q_ARG(
int
, i),
Q_ARG(QString, string));
>这样就能跨线程调用Qt动态库的函数;
Note invoke的格式必须严格遵守, 多一个空格就错, must stictly follow the format, e.g.:metaObj->indexOfMethod("Function(int,QString)"), no space is allowed between "int," and "QString".
对于MetaObject无法识别的类型: 使用qRegisterMetaType()来注册: "QMetaMethod::invoke: Unable to handle unregistered datatype 'MyType'"
使用invoke异步调用函数的时候, 是无法得到return的返回值的: "It is unable to QMetaObject::invokeMethod with return values in queued connections"
Solution: 1) 把函数的参数改为指针, 来传递想要得到的值; ---由于是在异步的消息机制下, 这个也是不行的;
所以只能这样: 2) 得到值以后再发个消息....或者调用Java对象的方法传递值;
---End---
- JNI和Qt通信 (Part 3)
- JNI和Qt通信 (Part 1)
- JNI和Qt通信 (Part 2)
- JNI加载Native Library 以及 跨线程和Qt通信
- JNI加载Native Library 以及 跨线程和Qt通信
- 《Qt》part 5 Qt5.5.0串口通信
- JNI-Java和C之间通信
- QT C++和HTML通信
- [ACE_Proactor网络通信示例-Part.3]
- 《MFC网络通信》Part 3 一般TCP通信
- Qt开发:TCP和UDP网络通信
- Qt TCP和UDP通信1
- Qt TCP和UDP通信2
- Part 01 走近Qt
- Part 01 走近Qt
- jni和C++通信中文乱码的问题
- jni和C++通信中文乱码的问题
- jni和C++通信中文乱码的问题
- (续)一种简陋的CC1100/CC1101主从通信协议
- ibatis对Mysql主从集群进行读写分离测试
- delphi - bpl与dll之关系
- ubuntu 12.04 安装 Nginx+PHP5 (PHP-FPM) 配置CI项目
- int main(int argc,char*argv[])的输入参数
- JNI和Qt通信 (Part 3)
- Windows Server 2003 注册码
- Delphi BPL包合并图文教程 IDEWiz tangram-plugin-framework
- Linux 常用命令
- GPIO宏定义一
- 项目常用js插件
- 迅雷在下载网页视频时没有自动弹出提示,怎么办?
- Ext.NETMultiCombo下拉列表 设置它的只读属性Editable 为True 好像不可以到达 只读效果问题。
- 语音编码标准