How to register a class method and a free method?

Forum for posting problems using QxOrm library

How to register a class method and a free method?

Postby alqfr » Thu Dec 06, 2012 8:45 pm

I don't see many posts on or examples of using methods. (I have submitted a patch for registering member functions with arguments - see the patch section of this forum.)

My question is how to register a class method and/or a free method (say with at least one argument). The two are probably equivalent.

Using QxClass<T>::fct_1 does not work and will create an error complaining a mismatch of argument types (involving T*). I have tried in vain invoking insert_fct (after making it public in QxClass) with qx::function::bind_fct_1 (it compiles but core-dumps), as follows:

template <> void register_class(QxClass<TestTable> & t)
{
...
t.insertFct(qx::function::bind_fct_1<TestTable, int, int>(
&TestTable::square), "square");
}

Does QxOrm support static/class methods natively? If so, how do I register a static method (or a free method for that matter)? If not, what code changes will make it work, and how soon will it make it to the next release? Even just some ideas will be great. I have a work-around by defining a new functor class to wrap around the static method and registering that functor class instead, but it could get tedious if you have a lot of static methods to register.
alqfr
 
Posts: 17
Joined: Thu Jul 19, 2012 3:47 pm

Re: How to register a class method and a free method?

Postby qxorm » Fri Dec 07, 2012 10:36 am

Hi,

I don't see many posts on or examples of using methods

Yes, this is not the main feature of QxOrm library :)

My question is how to register a class method and/or a free method...
Does QxOrm support static/class methods natively ?

Yes, QxOrm library supports static/class methods and free functions.
You have an example in the file : ./test/qxDllSample/exe/src/main.cpp of your QxOrm package.
Into this file, you can search :
* void test_fct() ==> for a free function example.

The goal is to provide a base class (or interface) to call in a generic way a function.
The base class is : qx::IxFunction.

So, for example with a free function :
Code: Select all
// Free function
void test_fct()
{ qDebug("[QxOrm] %s", "'test_fct()' called by 'qx::IxFunction()'"); }

// Register it to get a pointer to the base class qx::IxFunction
qx::IxFunction_ptr pFct1 = qx::function::bind_fct_0<void, void>(& test_fct);

// Execute the function in a generic way
qx_bool bInvoke = pFct1->invoke();


Here is another example using a static class method :
Code: Select all
// Static class method
struct test_class_fct
{ static int class_fct() { qDebug("[QxOrm] %s", "'test_class_fct::class_fct()' called by 'qx::IxFunction()'"); return 123; }; };

// Register it to get a pointer to the base class qx::IxFunction
qx::IxFunction_ptr pFct2 = qx::function::bind_fct_0<void, int>(& test_class_fct::class_fct);

// Execute the function in a generic way (and get the return value)
boost::any any_ret;
qx_bool bInvoke = pFct2->invoke("", (& any_ret));
qxorm
Site Admin
 
Posts: 481
Joined: Mon Apr 12, 2010 7:45 am

Re: How to register a class method and a free method?

Postby alqfr » Fri Dec 07, 2012 4:39 pm

Somehow, your forum timed me out, and I had to retype this. Please try and make your timeout long enough to express a thought with the necessary details (e.g., code), but I am typing my message elsewhere and pasting it here.

Thank you for supplying the important hints through examples. I was missing 2 important details.
  • I should have used void to replace TestTable when using qx::function::bind_fct_1<void, int, int> to create the qx::IxFunction_ptr.
  • To invoke the registered static method, I need to use the variant of the qx::IxFunction::invoke() method without the pOwner parameter in it.

But a deficiency is still spotted in the QxClass<T> API, namely that one should have been able to register a static method with the class that owns it, and I could only make it work as follows by making QxClass<T>::insertFct public first.
Code: Select all
// .cpp file
template <> void register_class(QxClass<TestTable> & t)
{
    ...
    t.insertFct(qx::function::bind_fct_1<void, int, int>(&TestTable::square), "square");
}


Now, in the test driver,
Code: Select all
string key = "square";
if (!fctList->exist(key.c_str())) {
     cout << key.c_str() << " non-existent" << endl;
     throw;
}
qx::IxFunction_ptr fct1 = fctList->getByKey(key.c_str());
int intRet;
int a = 3;
vector<boost::any> params(1);
params[0] = a;
//success = qx::QxClassX::invoke("TestTable", "square", *tablePtr, params, &ret);
//success = qx::QxClass<TestTable>::invoke("square", tablePtr.get(), params, &ret);
//intRet = boost::any_cast<int>(ret);
//cout << "square(" << a << ") = " << intRet << endl;

success = fct1->invoke(params, &ret);
intRet = boost::any_cast<int>(ret);
cout << "square(" << a << ") = " << intRet << endl;


So, a patch is still needed, i.e., to make QxClass<T>::insertFct public, or by making fct_1 (and other similar fct_? methods) support static method registration. Then, the static method will become locatable through reflection with its registered key ("square" in my case).

One additional thing. The static invoke methods in QxClassX and QxClass<T> seem to only support member methods. I could not get for example the commented lines in the code section above to work by zeroing the testTable pointer and/or by using an empty string to replace "TestTable". Any thought on this? This is not however urgent, as we only need one way to invoke a method.
alqfr
 
Posts: 17
Joined: Thu Jul 19, 2012 3:47 pm

Re: How to register a class method and a free method?

Postby qxorm » Fri Dec 07, 2012 6:44 pm

Please try and make your timeout long enough to express a thought with the necessary details

I don't know where is the option !
I just found it, with a value of 0 : Limit editing time: Limits the time available to edit a new post. Setting the value to 0 disables this behaviour.

But a deficiency is still spotted in the QxClass<T> API...

You are right, QxClass<T> needs new methods to register static method.
But, for free functions and static class methods, you could also imagine to register it yourself.
It's quite easy to do using a structure like this : boost::unordered_map<QString, qx::IxFunction_ptr>

The static invoke methods in QxClassX and QxClass<T> seem to only support member methods.

I will add new invoke methods if it's needed...
qxorm
Site Admin
 
Posts: 481
Joined: Mon Apr 12, 2010 7:45 am

Re: How to register a class method and a free method?

Postby alqfr » Fri Dec 07, 2012 7:21 pm

Thanks for your input and also fixing the timeout issue. You are probably the most responsive author I have had the pleasure of meeting online. :)

For free methods, I know I am going to have to use a map or hash_map to store the function pointers with their keys. While I can do the same for class methods, I think it is useful and stylistically satisfying to have a mechanism to register (in QxClass<T>) static methods with the class that owns it.

That said, these class methods behave like free methods, and even if they can be registered with QxClass<T>, one would still need to use a new flag/property from IxFunction itself to identify if the function is static, and if so, choose the correct invoke method. In addition, the name of the methods getFctMemberX() suggests that the returned list should only include member functions (and not class functions).

So, a better fix would probably be to define a new method or change the existing one, both for registering a static method, and for returning it, e.g.,
for registration:
insertFct(IxFunction_ptr pFct, const QString& sKey, bool isStatic = false)
or
insertClassFct(IxFunction_ptr pFct, const QString& sKey);
and for query:
renaming getFctMemberX() to getFctX() (to make the name inclusive of static methods), while also adding to IxFunction a new isStatic member data and a method to access it;
or
adding a new QxClass<T>::getClassFctX() that returns a new instance of IxFunctionsX containing only the list of class methods.

I personally favor the first approach of just adding a flag because adding a new IxFunctionsX is an overkill, and it is a good idea to have a single method return all the member and static methods at the same time (e.g., for documentation purposes, etc.).

I can do without the invoke() method in either QxClass<T> and QxClassX.
alqfr
 
Posts: 17
Joined: Thu Jul 19, 2012 3:47 pm

Re: How to register a class method and a free method?

Postby qxorm » Tue Dec 11, 2012 1:29 pm

Done, you can test it with the following BETA version :
http://www.qxorm.com/version/QxOrm_1.2.5_BETA_04.zip

You have an example with CPerson class :
Code: Select all
...
static int testStaticFct(const QString & s);
...
pFct = t.fctStatic_1<int, const QString &>(& qx::test::CPerson::testStaticFct, "fct_testStaticFct");
...
qx::QxClassX::invokeStatic("CPerson", "fct_testStaticFct", "182", (& resultInvoke));
...


I personally favor the first approach

Sorry, I prefer the second one ;)
qxorm
Site Admin
 
Posts: 481
Joined: Mon Apr 12, 2010 7:45 am

Re: How to register a class method and a free method?

Postby alqfr » Wed Dec 19, 2012 9:33 pm

The new 1.2.5-beta package aims to resolve 2 issues at once:
(i) registration/invocation of a static method (which is this thread); and
(ii) the invocation of functions with arguments (reported here viewtopic.php?f=4&t=339)

Here, I am only showing the results of testing issue #1. The results for issue #2 will be discussed in that thread (not working complete).

The 3 forms of static method invocation as shown below are all working. (BTW, I am perfectly fine with adding a new set of static method APIs.)
Code: Select all
        key = "square";
        qx::IxFunctionX *fctStaticList = type->getFctStaticX();
        if (!fctStaticList->exist(key.c_str())) {
            cout << "static method " << key.c_str()
                 << " not in static function list" << endl;
            throw;
        }
        qx::IxFunction_ptr fct1 = fctStaticList->getByKey(key.c_str());
        int intRet;
        int a = 3;
        vector<boost::any> params(1);
        params[0] = a;
        success = qx::QxClassX::invokeStatic("TestTable", key.c_str(), params, &ret);
        intRet = boost::any_cast<int>(ret);
        cout << "square(" << a << ") v0 = " << intRet << endl;

        success = qx::QxClass<TestTable>::invokeStatic(key.c_str(), params, &ret);
        intRet = boost::any_cast<int>(ret);
        cout << "square(" << a << ") v1 = " << intRet << endl;

        success = fct1->invoke(params, &ret);
        intRet = boost::any_cast<int>(ret);
        cout << "square(" << a << ") v2 = " << intRet << endl;
alqfr
 
Posts: 17
Joined: Thu Jul 19, 2012 3:47 pm

Re: How to register a class method and a free method?

Postby qxorm » Thu Dec 20, 2012 10:04 am

The 3 forms of static method invocation as shown below are all working.

Good newz ;)

Now, we will try to fix your second issue (from this topic http://www.qxorm.com/forum/phpbb/viewto ... 195ce46796)...
qxorm
Site Admin
 
Posts: 481
Joined: Mon Apr 12, 2010 7:45 am

Re: How to register a class method and a free method?

Postby alqfr » Thu Jan 03, 2013 2:50 pm

The new build 1.2.5_BETA_04 caused other parts of my code to give compilation error now, most of which are related to boost/archive/impl/basic_binary_iprimitive. Since I am on RHEL6, I am still using boost 1.41 which works with 1.2.4. So, what version of boost does 1.2.5_BETA_04 use? Thanks.

Update: My fault really. I should have included -D_QX_SERIALIZE_TEXT_ENABLED in the generated Makefiles before I built 1.2.5_BETA_04. My code is now working.
Last edited by alqfr on Thu Jan 03, 2013 4:19 pm, edited 1 time in total.
alqfr
 
Posts: 17
Joined: Thu Jul 19, 2012 3:47 pm

Re: How to register a class method and a free method?

Postby alqfr » Thu Jan 03, 2013 2:52 pm

Is there an ETA for the official release of 1.2.5?
alqfr
 
Posts: 17
Joined: Thu Jul 19, 2012 3:47 pm

Next

Return to QxOrm - Help

Who is online

Users browsing this forum: No registered users and 8 guests

cron