[PyQt] QSettings.registerFormat unavailable in PyQt4?

Phil Thompson phil at riverbankcomputing.com
Sat Jun 6 13:35:14 BST 2009


On Sat, 06 Jun 2009 12:17:21 +0200, Giovanni Bajo <rasky at develer.com>
wrote:
> On Sat, 06 Jun 2009 11:02:18 +0100, Phil Thompson
> <phil at riverbankcomputing.com> wrote:
>> On Sat, 06 Jun 2009 02:56:55 +0200, Giovanni Bajo <rasky at develer.com>
>> wrote:
>>> On Sat, 6 Jun 2009 01:19:39 +0200, David Boddie <david at boddie.org.uk>
>>> wrote:
>>>> On Fri Jun 5 19:25:01 BST 2009, Giovanni Bajo wrote:
>>>> 
>>>>> On 6/4/2009 10:18 PM, Phil Thompson wrote:
>>>> 
>>>>> > It can't be wrapped because of the nature of the function pointer
>>>>> > arguments - bad API design.
>>>>>
>>>>> Is it the same with Jambi?
>>>> 
>>>> I think so - look here:
>>>> 
>>>>
>>>
>>
>
http://doc.trolltech.com/qtjambi-4.5.0_01/com/trolltech/qt/core/QSettings.html
>>> 
>>> Given that there is no way to unregister a format, I think that there
is
>> a
>>> way to wrap it for PyQt: just prepare a fixed number of clones of
global
>>> read/write functions, that retrieve Python's callable objects from a
>>> fixed-size global array. Each time registerFormat() is used, save the
>> read
>>> and write function callables into the global arrays (incref'ing them
>>> forever, and using an ever growing counter that says how many custom
>>> formats have been registered); then, call the C++ version and pass it
> the
>>> pointers to the correct couple of clones of the global read/write
>>> functions.
>> 
>> How do you identify the correct couple of clones?
> 
> With a growing index. Let's see if this makes sense
> 
> 
> #define MAX_CUSTOM_FORMATS 3  // "ought to be enough for everyone"(TM)
> 
> int index = 0;
> PyObject *ReadCallable[MAX_CUSTOM_FORMATS];
> PyObject *WriteCallable[MAX_CUSTOM_FORMATS];
> 
> void ReadFunc0(args...) { invoke ReadCallable[0] with args }
> void ReadFunc1(args...) { invoke ReadCallable[1] with args }
> void ReadFunc2(args...) { invoke ReadCallable[2] with args }
> 
> void WriteFunc0(args...) { invoke WriteCallable[0] with args }
> void WriteFunc1(args...) { invoke WriteCallable[1] with args }
> void WriteFunc2(args...) { invoke WriteCallable[2] with args }
> 
> ReadFunc *ReadFuncTable[MAX_CUSTOM_FORMATS] = {
>      ReadFunc0, ReadFunc1, ReadFunc2
> };
> 
> WriteFunc *WriteFuncTable[MAX_CUSTOM_FORMATS] = {
>      WriteFunc0, WriteFunc1, WriteFunc2
> };
> 
> registerFormat(...)
> %MethodCode
>    if (index == MAX_CUSTOM_FORMATS) {
>       PyErr_Format(RuntimeError, "Sorry, PyQt supports only %d custom
> QSettings formats", MAX_CUSTOM_FORMATS);
>       return;
>    }
> 
>    PyObject *read = sipA1;
>    Py_INCREF(read);
>    ReadCallable[index] = read;
> 
>    PyObject *write = sipA2;
>    Py_INCREF(write);
>    WriteCallable[index] = write;
> 
>    QSettings::registerFormat(sipA0, ReadFuncTable[index],
> WriteFuncTable[index]);
> 
>    index++;
> %End
> 
> 
>> There's no problem with wrapping function pointers in themselves. What's
>> missing is that those functions should also take the QSettings::Format
as
>> an additional parameter. A good API will allow you to use a single
> callback
>> in all situations which requires that the callback is passed something
> that
>> allows it to identify the particular context.
> 
> Yes: but we can get away with this in this case because we can support a
> bounded number of custom formats without probably noone ever hitting the
> limit.

I agree that that would work. If I can get over my strong sense of distaste
I might implement it.

Phil


More information about the PyQt mailing list