How qml call static method from c++ - c++11

What I done:
validator.h:
class UTILSSHARED_EXPORT Validator: public QObject {
Q_OBJECT
public:
Validator(QObject *parent = 0);
~Validator();
Q_INVOKABLE static bool validateMobile(const QString target);
};
main.cpp:
qmlRegisterUncreatableType<Validator>("CT.Utils", 1, 0, "ValidatorKit", "It just a kit");
qml:
import CT.Utils 1.0
ValidatorKit.validateMobile("112344")
But unfortunately, I got an error that said: TypeError: Property 'validateMobile' of object [object Object] is not a function
So, how can I expose static method to qml correctly?
Could anybody help me? Thanks a lot.

qmlRegisterUncreatableType() is about something else entirely.
What you actually need to do is expose a Validator instance as a context property to QML, or even better, implement the validator as a singleton.
qmlRegisterSingletonType<Validator>("CT.Utils", 1, 0, "ValidatorKit", fooThatReturnsValidatorPtr);

Addition to singleton type, it is possible to create a private singleton attached properties object which contains only static functions. It is more clear with an example:
class StaticValidator;
class Validator : public QObject {
Q_OBJECT
public:
Validator(QObject *parent = 0);
~Validator();
// Put implementation in a source file to prevent compile errors.
static StaticValidator* qmlAttachedProperties(QObject *object) {
Q_UNUSED(object);
static StaticValidator instance;
return &instance;
}
static bool validateMobile(const QString& target);
};
//Q_OBJECT does not work in inner classes.
class StaticValidator : public QObject {
Q_OBJECT
public:
Q_INVOKABLE inline bool validateMobile(const QString& target) const {
return Validator::validateMobile(target);
}
private:
StaticValidator(QObject* parent = nullptr) : QObject(parent) {}
friend class Validator;
};
QML_DECLARE_TYPE(Validator)
QML_DECLARE_TYPEINFO(Validator, QML_HAS_ATTACHED_PROPERTIES)
Register type in main or somewhere:
qmlRegisterType<Validator>("Validator", 1, 0, "Validator");
Call function in QML:
import Validator 1.0
...
var result = Validator.validateMobile(target);
It should also work in Qt4, but I didn't test it.

Related

How can I access a protected variable in child class through an abstract class pointer?

I have an abstract class that I have derived from two child classes. One of them has a protected variable that the other one does not. To make the code more general, I have to use an smart pointer of the abstract class. Is there any way to access the protected variable through the pointer? As an example, Consider the following code (the real code is huge and I had to write this sample code):
class Pen{
public:
pen(string _color): color(_color){};
getColor(){return color;};
protected:
string color;
};
// base abstract class
class writer{
public:
writer() {}
virtual changeColor(string color) = 0;
};
class oldWriter: public writer{
protected:
Pen *pen;
public:
oldWriter(string _pen):
pen(_pen){}
virtual changeColor(string color){ pen->color = color;};
};
class youngWriter: public writer{
protected:
Pen *pen;
Pencile pencil; //we need to have access to pencil
public:
youngWriter(string _pen):
pen(_pen){}
virtual changeColor(string color){ pen->color = color;};
Pencil getPencil(){return pencil;};
};
int main(){
unique_ptr<Writer> artist;
Pencil pencil = artist->getPencil(); //how?
}
How can we access "pencil" in "youngWriter" class through "artist"?
if i well understood the code, the problem is related to class "Writer" which haven't a method called getPencil.
getPencil is a method of class youngWriter.
Therefore:
artist have to be a youngWriter instance.
Writer have to contains a method getPencil abstract.

Instantiation of virtual member function with templated return type

I have a base class (with which I want to simulate interfaces)
template<typename TType>
class Base
{
public:
virtual SomeTemplatedClass<TType> GetTheObject() = 0;
}
and obviously a derived class
template<typename TType>
class Derived : public Base<TType>
{
public:
virtual SomeTemplatedClass<TType> GetTheObject() = 0;
}
but for some specific type I have the intention to specialize the 'GetTheObject'
template<>
SomeTemplatedClass<int> Derived<int>::GetTheObject()
{
return 5;
}
Visual Studio 2015 complains it cannot instantiate abstract class, when I try to use
Derived<int>
Providing even a throwing behavior to a template version
class Derived : public Base<TType>
{
public:
virtual SomeTemplatedClass<TType> GetTheObject() override
{
throw <something>;
}
}
Let everything compile.
So my question is: Why do i need to provide a generic behavior, when I have a specific one and the only one that is needed?
You don't need to implement the generic GetTheObject, but you need to declare it as non-pure. Otherwise your class is abstract.
template<typename TType>
class Derived : public Base<TType>
{
public:
virtual SomeTemplatedClass<TType> GetTheObject();
}
You can specialise the function now.
You won't be able to instantiate any non-specialised derived objects (you will get linker errors).
You cannot make an abstract class into concrete by simply providing an implementation of its pure virtual member outside of the class.
class A { virtual void f() = 0; }; // A is abstract
void A::f() {} // A is still abstract
Templates are no different.
template <int> class A { virtual void f() = 0; }; // A is abstract
template <int k> void A<k>::f() {} // A is still abstract
A function specialisation changes nothing.
template <int> class A { virtual void f() = 0; }; // A is abstract
template <int k> void A<k>::f() {} // A is still abstract
template <> void A<42>::f() {} // srsly are you kidding?
If you want the generic case to be abstract and the specialised case concrete, you need to specialise the entire class, not just the pure function implementation.

JNA : Error when to call natives functions with pointer to struture as parameters

I tested this int EMV_Init(EMV_PARAMS *params, EMV_HANDLE *hEMV) in C, it works well.
Now i want to call it in my java application by means of jna. This function is in a native library under windows (dll file).
EMV_PARAMS is a structure
typedef struct
{
HAL_UI_HANDLE ui;
HAL_SCR_HANDLE card;
HAL_PROPERTY_HANDLE property;
HAL_DATE_HANDLE date;
HAL_CRYPTO_HANDLE crypto;
HAL_CHV_HANDLE chv;
} EMV_PARAMS;
Note that all attributes in EMV_PARAMS is is an opaque structure like this typedef void * HAL_UI_HANDLE;
EMV_HANDLE is also an opaque structure : typedef void *EMV_HANDLE;
I need your help to fix the following error:
Exception in thread "main" java.lang.NullPointerException at
com.sun.jna.Structure.getFields(Structure.java:895)
at com.sun.jna.Structure.deriveLayout(Structure.java:1042)
at com.sun.jna.Structure.calculateSize(Structure.java:966)
at com.sun.jna.Structure.calculateSize(Structure.java:933)
at com.sun.jna.Structure.allocateMemory(Structure.java:360)
at com.sun.jna.Structure.<init>(Structure.java:184)
at com.sun.jna.Structure.<init>(Structure.java:172)
at com.sun.jna.Structure.<init>(Structure.java:159)
at com.sun.jna.Structure.<init>(Structure.java:151)
I created a Java interface named "CInterface" which contains "EMV_PARAMS" class.
public interface CInterface extends Library
{
CInterface INSTANCE = (CInterface) Native.loadLibrary("path to dll", CInterface.class);
public int EMVCT_Init(EMV_PARAMS.ByReference params, Pointer hEMV);
public static class PARAMS extends Structure
{
public static class ByReference extends PARAMS implements Structure.ByReference {}
Pointer ui;
Pointer card;
Pointer property;
Pointer date;
Pointer crypto;
Pointer chv;
#Override
protected List getFieldOrder() {
// TODO Auto-generated method stub
return null;
}
}
}
java test class
public static void main(String[] args)
{
CInterface.EMV_PARAMS.ByReference emv_param = new
CInterface.EMV_PARAMS.ByReference();
int test= 0;
Pointer hEMV = null;
test=CInterfaceEMV.INSTANCE.EMVCT_Init(emv_param, hEMV);
System.out.println("test="+test);
}
Thank you for your attention
Your structure fields must be public, and you need to implement getFieldOrder().

Casting an object with events defined to an interface type causes an internal compiler error

I've got an interface with a simple signature:
namespace Serial {
public interface struct ISerial
{
uint16_t func1();
uint16_t func2();
};
}
and then a class type which implements the interface
namespace Serial {
public delegate void MyEventClass();
public ref class MySerial sealed : public ISerial {
public:
event MyEventClass MyEvent;
MySerial();
...
};
}
but elsewhere, as a default parameter to a function, I try to store a reference to a type MySerial as an ISerial ^
void
begin(
Serial::ISerial ^s = ref new Serial::MySerial
);
causes: error C1001: An internal error has occurred in the compiler.
when I remove the event from the class definition, everything compiles fine. I'm finding little information on this error.
I verified this on VS 2013 and it works with a few minor changes (all generated based on normal compiler errors, not an ICE). I don't have VS 2015 available right now, but will log a bug if it still repros.
First the struct (should be unchanged)
namespace Serial
{
public interface struct ISerial
{
uint16_t func1();
uint16_t func2();
};
}
Then the class (couple of changes noted below):
namespace Serial
{
public delegate void MyEventClass();
public ref class MySerial sealed : public ISerial{
public:
event MyEventClass^ MyEvent;
MySerial(){}
virtual uint16_t func1() { return 42; }
virtual uint16_t func2() { return 42; }
};
}
And the usage:
void foo()
{
using namespace Serial;
ISerial^ foo = ref new MySerial();
}
Basically you need to add the hat (^) to the event type, and you need to add virtual to the methods (but do not add override).
See more here on MSDN

C++/CLI Generic::Dictionary Declaration Syntax

I'm been curious about the declaration syntax of Collections::Generic::Dictionary
class in C++/CLI.
Normally we declare a reference in a class and initialize it:
public ref class CDemo {
private: ClassA ^ m_InstanceA;
// Why the absence of '^'.
private: Dictionary<int, int> m_Dic;
CDemo() :
m_InstanceA(gcnew ClassA()),
m_Dic(gcnew Dictionary<int, int>())
{...}
};
Could someone explains please why should the '^' absent there?
What's more, if I were to use the dictionary above as a TValue of another dictionary,
I have to declare it like this:
Dictionary<T, Dictionary<T, T>^ > m_Dic; // A '^' in the TValue parameter, which is
// normal, but same question as above,
// I don't have to declare m_Dic as ^ ?
Thanks.
This is not specific to Dictionary. This syntax is a way to help map C++ semantics onto managed types. In general:
ref class A
{
ReferenceType m_obj;
};
is roughly equivalent to
class A : IDisposable
{
private ReferenceType m_obj;
void Dispose() { m_obj.Dispose(); }
}
in C# if ReferenceType implements IDisposable. It is perfectly possible to write
ref class A
{
ReferenceType^ m_obj;
};
This does not have the implicit IDisposable support. The other difference is that you can return a ReferenceType^ from a method, this is not supported with just plain ReferenceType. For example:
ref class A
{
ReferenceType^ m_obj;
ReferenceType^ GetIt() { return m_obj; }
};
will compile,
ref class A
{
ReferenceType m_obj;
ReferenceType GetIt() { return m_obj; } // won't compile
ReferenceType^ OtherGetIt() { return m_obj; } // neither will this
};
A similar distinction is provided for automatic (stack variables)
ReferenceType local;
local.Stuff();
is desugared by the compiler to
try {
ReferenceType^ local = gcnew ReferenceType();
local->Stuff();
} finally {
delete local; // invokes Dispose() (~ReferenceType)
}
These features bring the familiar idiom of RAII to C++/CLI with managed types.
EDIT:
Yes, the Dispose method of IDisposable is analogous to a C++ destructor. If ReferenceType doesn't implement IDisposable (doesn't have a dtor), and it is the only member, A will also not implement IDisposable (not have an implicit dtor). In C++/CLI you implement IDisposable by providing a dtor (for managed types).

Resources