mirror of
https://gitlab.com/eql/lqml.git
synced 2025-12-06 02:30:38 -08:00
add cpp-lib example; some fixes
This commit is contained in:
parent
7a4bff3c20
commit
eb54b6fd41
12 changed files with 144 additions and 11 deletions
14
cpp-lib/cpp/cpp.pro
Normal file
14
cpp-lib/cpp/cpp.pro
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
QT += core
|
||||||
|
TEMPLATE = lib
|
||||||
|
CONFIG += plugin release
|
||||||
|
DESTDIR = ../
|
||||||
|
TARGET = cpp
|
||||||
|
OBJECTS_DIR = ./tmp/
|
||||||
|
MOC_DIR = ./tmp/
|
||||||
|
|
||||||
|
win32 {
|
||||||
|
include(../../src/windows.pri)
|
||||||
|
}
|
||||||
|
|
||||||
|
HEADERS += lib.h
|
||||||
|
SOURCES += lib.cpp
|
||||||
27
cpp-lib/cpp/lib.cpp
Normal file
27
cpp-lib/cpp/lib.cpp
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include "lib.h"
|
||||||
|
#include <QtDebug>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
QObject* ini() {
|
||||||
|
// any QObject inherited class will do
|
||||||
|
static QObject* cpp = 0;
|
||||||
|
if(!cpp) {
|
||||||
|
cpp = new CPP;
|
||||||
|
}
|
||||||
|
return cpp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert here your function implementations
|
||||||
|
|
||||||
|
QVariant CPP::hello(const QVariant& arg) {
|
||||||
|
QString msg;
|
||||||
|
QDebug debug(&msg);
|
||||||
|
debug << arg;
|
||||||
|
|
||||||
|
qDebug() << "hello" << arg;
|
||||||
|
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
28
cpp-lib/cpp/lib.h
Normal file
28
cpp-lib/cpp/lib.h
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef LIB_H
|
||||||
|
#define LIB_H
|
||||||
|
|
||||||
|
#include <QtCore>
|
||||||
|
|
||||||
|
#ifdef Q_CC_MSVC
|
||||||
|
#define LIB_EXPORT __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define LIB_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
extern "C" { LIB_EXPORT QObject* ini(); }
|
||||||
|
|
||||||
|
class CPP : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
// max. 10 arguments of type QVariant
|
||||||
|
// return type must also be a QVariant
|
||||||
|
Q_INVOKABLE QVariant hello(const QVariant&);
|
||||||
|
};
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif
|
||||||
39
cpp-lib/readme.md
Normal file
39
cpp-lib/readme.md
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
|
||||||
|
Build
|
||||||
|
-----
|
||||||
|
|
||||||
|
Switch to `cpp/` and do:
|
||||||
|
```
|
||||||
|
qmake lib.pro
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Run
|
||||||
|
---
|
||||||
|
|
||||||
|
```
|
||||||
|
$ lqml ~/slime/qml-start-swank.lisp
|
||||||
|
$ emacs
|
||||||
|
```
|
||||||
|
|
||||||
|
In Slime do:
|
||||||
|
```
|
||||||
|
(defvar *cpp* (qload-c++ "cpp"))
|
||||||
|
|
||||||
|
(define-qt-wrappers *cpp*)
|
||||||
|
|
||||||
|
(hello *cpp* '(1 "two" (1.25 #(50 -50 75))))
|
||||||
|
```
|
||||||
|
Now look at the console output where you launched the `lqml` executable.
|
||||||
|
|
||||||
|
As you can see, although the argument and return type are simply defined as
|
||||||
|
`QVariant`, you may also pass lists, because a `QVariant` can also be of type
|
||||||
|
`QVariantList`, so this is a perfect fit for (nested) Lisp lists.
|
||||||
|
|
||||||
|
So, we pass a nested Lisp list, and it gets printed on Qt side with the
|
||||||
|
respective types. Then the `QVariantList` is returend to Lisp, where it is
|
||||||
|
automatically converted back to a nested Lisp list.
|
||||||
|
|
||||||
|
Realy convenient!
|
||||||
|
|
||||||
6
cpp-lib/run.lisp
Normal file
6
cpp-lib/run.lisp
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
(defvar *cpp* (qload-c++ "cpp"))
|
||||||
|
|
||||||
|
(define-qt-wrappers *cpp*)
|
||||||
|
|
||||||
|
(print (hello *cpp* '(1 "two" (1.25 #(50 -50 75)))))
|
||||||
|
|
||||||
13
doc/help.htm
13
doc/help.htm
|
|
@ -24,6 +24,16 @@
|
||||||
(define-qt-wrappers *c++*) ; Lisp wrapper functions
|
(define-qt-wrappers *c++*) ; Lisp wrapper functions
|
||||||
|
|
||||||
|
|
||||||
|
<b>define-qt-wrappers (qt-library &rest what)</b>
|
||||||
|
|
||||||
|
Defines Lisp methods for all Qt methods/signals/slots of given library,
|
||||||
|
previously loaded with QLOAD-C++.
|
||||||
|
|
||||||
|
(define-qt-wrappers *c++*) ; generate wrappers
|
||||||
|
(define-qt-wrappers *c++* :methods) ; Qt methods only (no slots/signals)
|
||||||
|
(my-qt-function *c++* x y) ; call from Lisp
|
||||||
|
|
||||||
|
|
||||||
<b>find-quick-item (object-name)</b>
|
<b>find-quick-item (object-name)</b>
|
||||||
|
|
||||||
Finds the first QQuickItem matching OBJECT-NAME. Locally set *ROOT-ITEM* if
|
Finds the first QQuickItem matching OBJECT-NAME. Locally set *ROOT-ITEM* if
|
||||||
|
|
@ -125,7 +135,8 @@
|
||||||
|
|
||||||
Fast and convenient way to call JS functions defined in QML. You may pass
|
Fast and convenient way to call JS functions defined in QML. You may pass
|
||||||
up to 10 arguments of the following types:
|
up to 10 arguments of the following types:
|
||||||
T, NIL, INTEGER, FLOAT, STRING, and (nested) lists of mentioned arguments.
|
T, NIL, INTEGER, FLOAT, STRING, VECTOR of octets, and (nested) lists of
|
||||||
|
mentioned arguments.
|
||||||
N.B: Does not work with JS default arguments.
|
N.B: Does not work with JS default arguments.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,5 +27,4 @@ TODO
|
||||||
* make example work on iOS
|
* make example work on iOS
|
||||||
* add item model example
|
* add item model example
|
||||||
* add sokoban example
|
* add sokoban example
|
||||||
* add cpp-lib example
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -250,7 +250,8 @@ cl_object qload_cpp(cl_object l_lib_name, cl_object l_unload) { /// qload-c++
|
||||||
if (ini) {
|
if (ini) {
|
||||||
QObject* main = ini();
|
QObject* main = ini();
|
||||||
if (main) {
|
if (main) {
|
||||||
ecl_return1(ecl_process_env(), ECL_T);
|
cl_object l_ret = from_qobject_pointer(main);
|
||||||
|
ecl_return1(ecl_process_env(), l_ret);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -391,8 +392,9 @@ cl_object qlog2(cl_object l_msg) {
|
||||||
cl_object qinvoke_method2(cl_object l_obj, cl_object l_name, cl_object l_args) {
|
cl_object qinvoke_method2(cl_object l_obj, cl_object l_name, cl_object l_args) {
|
||||||
// for internal use: this is used to call user defined JS functions, and to
|
// for internal use: this is used to call user defined JS functions, and to
|
||||||
// call user defined Qt/C++ plugin functions.
|
// call user defined Qt/C++ plugin functions.
|
||||||
// Max. 10 arguments of type T, NIL, INTEGER, FLOAT, STRING, (nested) LIST of
|
// Max. 10 arguments of type T, NIL, INTEGER, FLOAT, STRING, VECTOR of
|
||||||
// mentioned arguments. On Qt side, only QVariant arguments are allowed.
|
// octets, (nested) LIST of mentioned arguments. On Qt side, only QVariant
|
||||||
|
// arguments are allowed.
|
||||||
// N.B. does not support default arguments, if used to call JS functions
|
// N.B. does not support default arguments, if used to call JS functions
|
||||||
ecl_process_env()->nvalues = 1;
|
ecl_process_env()->nvalues = 1;
|
||||||
const int MAX = 10;
|
const int MAX = 10;
|
||||||
|
|
|
||||||
|
|
@ -132,9 +132,10 @@ TO_QT_FLOAT_4 (QRectF)
|
||||||
QVariant toQVariant(cl_object l_arg, int type) {
|
QVariant toQVariant(cl_object l_arg, int type) {
|
||||||
QVariant var;
|
QVariant var;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case QMetaType::QPointF: var = toQPointF(l_arg); break;
|
case QMetaType::QByteArray: var = toQByteArray(l_arg); break;
|
||||||
case QMetaType::QRectF: var = toQRectF(l_arg); break;
|
case QMetaType::QPointF: var = toQPointF(l_arg); break;
|
||||||
case QMetaType::QSizeF: var = toQSizeF(l_arg); break;
|
case QMetaType::QRectF: var = toQRectF(l_arg); break;
|
||||||
|
case QMetaType::QSizeF: var = toQSizeF(l_arg); break;
|
||||||
default:
|
default:
|
||||||
if (cl_integerp(l_arg) == ECL_T) { // int
|
if (cl_integerp(l_arg) == ECL_T) { // int
|
||||||
var = QVariant(toInt(l_arg));
|
var = QVariant(toInt(l_arg));
|
||||||
|
|
@ -154,6 +155,9 @@ QVariant toQVariant(cl_object l_arg, int type) {
|
||||||
else if (cl_listp(l_arg) == ECL_T) { // list
|
else if (cl_listp(l_arg) == ECL_T) { // list
|
||||||
var = QVariant::fromValue(toQVariantList(l_arg));
|
var = QVariant::fromValue(toQVariantList(l_arg));
|
||||||
}
|
}
|
||||||
|
else if (cl_vectorp(l_arg) == ECL_T) { // vector (of octets)
|
||||||
|
var = QVariant(toQByteArray(l_arg));
|
||||||
|
}
|
||||||
else { // default: undefined
|
else { // default: undefined
|
||||||
var = QVariant();
|
var = QVariant();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,8 @@
|
||||||
(define-qt-wrappers *c++*) ; generate wrappers
|
(define-qt-wrappers *c++*) ; generate wrappers
|
||||||
(define-qt-wrappers *c++* :methods) ; Qt methods only (no slots/signals)
|
(define-qt-wrappers *c++* :methods) ; Qt methods only (no slots/signals)
|
||||||
(my-qt-function *c++* x y) ; call from Lisp"
|
(my-qt-function *c++* x y) ; call from Lisp"
|
||||||
(let ((all-functions (qapropos* nil (ensure-qt-object qt-library)))
|
(assert (qobject-p qt-library))
|
||||||
|
(let ((all-functions (qapropos* nil qt-library))
|
||||||
(lispify (not (find :do-not-lispify what))))
|
(lispify (not (find :do-not-lispify what))))
|
||||||
(setf what (remove-if (lambda (x) (find x '(:do-not-lispify t)))
|
(setf what (remove-if (lambda (x) (find x '(:do-not-lispify t)))
|
||||||
what))
|
what))
|
||||||
|
|
@ -142,7 +143,7 @@
|
||||||
;; there seems to be no simple way to avoid EVAL here
|
;; there seems to be no simple way to avoid EVAL here
|
||||||
;; (excluding non-portable hacks)
|
;; (excluding non-portable hacks)
|
||||||
(eval `(defgeneric ,lisp-name (object &rest arguments)))
|
(eval `(defgeneric ,lisp-name (object &rest arguments)))
|
||||||
(eval `(defmethod ,lisp-name ((object qt-object) &rest arguments)
|
(eval `(defmethod ,lisp-name ((object si:foreign-data) &rest arguments)
|
||||||
(%qinvoke-method object ,qt-name arguments)))))))))
|
(%qinvoke-method object ,qt-name arguments)))))))))
|
||||||
|
|
||||||
(defun qinvoke-method (object function-name &rest arguments)
|
(defun qinvoke-method (object function-name &rest arguments)
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#:*root-item*
|
#:*root-item*
|
||||||
#:*caller*
|
#:*caller*
|
||||||
#:children
|
#:children
|
||||||
|
#:define-qt-wrappers
|
||||||
#:find-quick-item
|
#:find-quick-item
|
||||||
#:js
|
#:js
|
||||||
#:make-qobject
|
#:make-qobject
|
||||||
|
|
|
||||||
|
|
@ -179,7 +179,8 @@
|
||||||
"args: (method-name item/name &rest arguments
|
"args: (method-name item/name &rest arguments
|
||||||
Fast and convenient way to call JS functions defined in QML. You may pass
|
Fast and convenient way to call JS functions defined in QML. You may pass
|
||||||
up to 10 arguments of the following types:
|
up to 10 arguments of the following types:
|
||||||
T, NIL, INTEGER, FLOAT, STRING, and (nested) lists of mentioned arguments.
|
T, NIL, INTEGER, FLOAT, STRING, VECTOR of octets, and (nested) lists of
|
||||||
|
mentioned arguments.
|
||||||
N.B: Does not work with JS default arguments."
|
N.B: Does not work with JS default arguments."
|
||||||
`(qrun* (qfun (quick-item ,item/name)
|
`(qrun* (qfun (quick-item ,item/name)
|
||||||
,(if (symbolp method-name)
|
,(if (symbolp method-name)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue