Re: [GNC-dev] Python-Bindings: issue when C expects GList argument

"Derek Atkins" <[email protected]>
Newsgroups gmane.comp.gnome.apps.gnucash.devel
Message-ID <[email protected]>
More specifically...

The issue here is that there are multiple return values.  
gncOwnerCreatePaymentLotSecs() is *RETURNING* both a GNCLot* and a
Transaction*.  However, C doesn't allow you to do that, so the function
returns the GNCLot* and assigns the Transaction* to the Transaction**
argument as a second return value.

Your proposed wrapper here is wrong.

You can either write a wrapper that obtains the transaction and then
unrefs it (returning only the Lot), or you can write a wrapper that
obtains both values and returns the tuple (Lot, Txn) in Python -- assuming
Python, like Scheme, allows that.

Most likely this is why the function wasn't wrapped before -- due to the
complexities of the double return values.

-derek

On Tue, May 10, 2022 5:23 pm, Matteo Lasagni wrote:
> If I can find a good solution, yes, I will put it in a pull request.
>
> I have tried to encapsulate Transaction* in a list, but of course it
> doesn't work without touching swig definitions.
> I am now trying to create a specific typemap for handling the double
> pointer. I think this would be the cleanest solution.
>
> Alternatively, a quick and dirty workaround is to add a C wrapper in
> gncOwner.c that expects Transaction* and passes Transaction** to
> gncOwnerCreatePaymentLotSecs:
>
>
> GNCLot *
> gncOwnerCreatePaymentLotSecsPyHelper (const GncOwner *owner, Transaction
> *txn, Account *posted_acc, Account *xfer_acc, gnc_numeric amount,
> gnc_numeric exch, time64 date, const char *memo, const char *num)
> {
>     return gncOwnerCreatePaymentLotSecs(owner, &txn, posted_acc, xfer_acc,
> amount, exch, date, memo, num);
> }
>
>
> regards,
> Matteo
>
> On Tue, 10 May 2022 at 17:25, john <[email protected]> wrote:
>
>>
>>
>> On May 10, 2022, at 1:53 AM, Matteo Lasagni <[email protected]> wrote:
>>
>> Thank you, John!
>>
>> I fixed it by adding the following into base-typemaps.i:
>>
>> %typemap(in) GList * {
>>     $1 = NULL;
>>     /* Check if is a list */
>>     if (PyList_Check($input)) {
>>         int i;
>>         int size = PyList_Size($input);
>>         for (i = size-1; i >= 0; i--) {
>>             PyObject *o = PyList_GetItem($input, i);
>>             $1 = g_list_prepend($1, o);
>>         }
>>     } else {
>>         PyErr_SetString(PyExc_TypeError, "not a list");
>>         return NULL;
>>     }
>> }
>>
>> I had overlooked the swig definition in engine.i, where there is a
>> typemap
>> (in) for GList, but then it is cleared right afterwards...
>> I am not (yet) very familiar with swig :-)
>>
>> I have also noticed that CreatePaymentLotSecs does not work out of the
>> box, as it expects **Transaction while only *Transaction is type mapped.
>>
>> I will test these changes then I will figure out how to share them with
>> the developers.
>>
>>
>> Matteo
>>
>>
>> On Tue, 10 May 2022 at 02:32, John Ralls <[email protected]> wrote:
>>
>>>
>>>
>>> > On May 9, 2022, at 2:17 PM, Matteo Lasagni <[email protected]>
>>> wrote:
>>> >
>>> > Hi,
>>> > I am writing a python script to automatically associate a set of
>>> > invoices to a single transaction.
>>> > To this end, I am trying to use the function
>>> AutoApplyPaymentsWithLots
>>> > with no success:
>>> >
>>> >
>>> > lots = [lot1, lot2, lotn, ..]
>>> > owner.AutoApplyPaymentsWithLots(lots)
>>> >
>>> > This causes the following error:
>>> >
>>> > TypeError: in method 'gncOwnerAutoApplyPaymentsWithLots', argument 2
>>> of
>>> > type 'GList *'
>>> >
>>> > I have tried different solutions from passing different types of
>>> python
>>> > objects, to updating the swig typemap and also to modifying the
>>> > auto-generated gnucash_core.c...nothing worked out so far.
>>> > I could write an additional c-wrapper, but I am sure there is a more
>>> > general solution.
>>>
>>> The fundamental problem is that there's only a Python out typemap for
>>> GList, that is one that converts from a GList* to a python list.
>>> Lacking an
>>> in typemap the gncOwner.AutoApplyPaymentsWithLots python wrapper
>>> expects an
>>> already constructed and Swig-wrapped GList*.
>>>
>>> Regards,
>>> John Ralls
>>>
>>>
>>
>> Nice. Would you put that in a pull request?
>>
>> There are two typemap(in) GList* in engine.i, but they're both for Guile
>> (Scheme), not Python. 'scm' is the giveaway.
>>
>> If there's a way to implement an output pointer parameter in Python I
>> don't know about it. You can pass in a container object and put the
>> output
>> Transaction* in the container, but that's both a bit of a hack and
>> doesn't
>> have the same meaning as Transaction** nor is it very pythonic. Nor, for
>> that matter, is gncOwnerCreatePaymentLotSecs a very good design as it
>> mixes
>> responsibilities. Unfortunately there's a lot of that in GnuCash because
>> most of it is written with a very narrow focus, in this case providing
>> for
>> the payments dialog.
>>
>> Regards,
>> John Ralls
>>
>>
>
> --
>
> -------------
> Matteo Lasagni
>
>
> *"You can't connect the dots looking forward,you can only connect them
> looking backwards"* [Steve Jobs]
> _______________________________________________
> gnucash-devel mailing list
> [email protected]
> https://lists.gnucash.org/mailman/listinfo/gnucash-devel
>


-- 
       Derek Atkins                 617-623-3745
       [email protected]             www.ihtfp.com
       Computer and Internet Security Consultant
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.