From: Simon B. <sim...@uc...> - 2012-08-22 06:47:57
|
Hello, I'm currently using SWIG to wrap a C library. I found a weird behaviour and wanted to know if this is a bug or not, and how can I fix this. Here is my problem: I have a function returning a pointer (I used in the example below a pointer to an int for illustration, but in my case it's a pointer to a structure); in addition, it uses an argument to return another output (i.e. an argument is a pointer to an int that is filled by the function). Here is my example: int* test(int arg, int* error) { int *res; if(arg > 0) { res = (int *) 1; *error = 0; } else { res = NULL; *error = 1; } return res; } I wrapped this with SWIG and applied a typemap on int* error to tell that it is also an output. Here is my SWIG interface: %include "typemaps.i" %apply int *OUTPUT {int* error}; %inline %{ int* test(int arg, int* error) { int *res; if(arg > 0) { res = (int *) 1; *error = 0; } else { res = NULL; *error = 1; } return res; } %} So, when I use the module generated by SWIG with Python, I get this behaviour: >>> test(1) [<Swig Object of type 'int *' at 0x1006bdde0>, 0] >>> test(0) 1 It seems that when the function returns a NULL pointer, the output is ignored and only the int* error output is used. Is it a bug or not? How can I fix this, such that when the result is NULL I get "[None, 1]" in Python instead of just "1"? I can't modify the initial function. Thank you very much for your help, Regards, Simon Busard PS: I checked the manual but found nothing. Please forgive me if the answer was there but I missed it. |
From: Марк К. <soc...@gm...> - 2012-08-22 07:13:30
|
2012/8/22 Simon Busard <sim...@uc...> > Hello, > > I'm currently using SWIG to wrap a C library. I found a weird behaviour > and wanted to know if this is a bug or not, and how can I fix this. Here > is my problem: I have a function returning a pointer (I used in the > example below a pointer to an int for illustration, but in my case it's > a pointer to a structure); in addition, it uses an argument to return > another output (i.e. an argument is a pointer to an int that is filled > by the function). Here is my example: > > > int* test(int arg, int* error) { > int *res; > if(arg > 0) { > res = (int *) 1; > *error = 0; > } else { > res = NULL; > *error = 1; > } > return res; > } > > > I wrapped this with SWIG and applied a typemap on int* error to tell > that it is also an output. Here is my SWIG interface: > > > %include "typemaps.i" > > %apply int *OUTPUT {int* error}; > > %inline %{ > > int* test(int arg, int* error) { > int *res; > if(arg > 0) { > res = (int *) 1; > *error = 0; > } else { > res = NULL; > *error = 1; > } > return res; > } > > %} > > > So, when I use the module generated by SWIG with Python, I get this > behaviour: > > > >>> test(1) > [<Swig Object of type 'int *' at 0x1006bdde0>, 0] > >>> test(0) > 1 > > > It seems that when the function returns a NULL pointer, the output is > ignored and only the int* error output is used. > > Is it a bug or not? How can I fix this, such that when the result is > NULL I get "[None, 1]" in Python instead of just "1"? I can't modify the > initial function. > > Thank you very much for your help, > > Regards, > > Simon Busard > > > PS: I checked the manual but found nothing. Please forgive me if the > answer was there but I missed it. > You should write wrapper for that function. It's SWIG, baby. Yes, I have the same problem (Some library function return result in two output parameters (retval and via pointer in arg)), so, I have [<result>, <result>] in stead of just <result>. So I asked this mailing list for help, and people advice me to write a wrapper in .i file, and then export wrapper instead of original function. > > > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and > threat landscape has changed and how IT managers can respond. Discussions > will include endpoint security, mobile security and the latest in malware > threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > _______________________________________________ > Swig-user mailing list > Swi...@li... > https://lists.sourceforge.net/lists/listinfo/swig-user > -- Segmentation fault |
From: Simon B. <sim...@uc...> - 2012-08-22 07:41:09
|
But here I want the [<retval>, <arg>] behaviour. The problem is that when retval is NULL (i.e. the function returns a NULL pointer as retval), this value is not given by the wrapper and the result is <arg>, while I want [<None>, <arg>]. Le Wed Aug 22 09:13:19 2012, Марк Коренберг a écrit : > > > 2012/8/22 Simon Busard <sim...@uc... > <mailto:sim...@uc...>> > > Hello, > > I'm currently using SWIG to wrap a C library. I found a weird > behaviour > and wanted to know if this is a bug or not, and how can I fix > this. Here > is my problem: I have a function returning a pointer (I used in the > example below a pointer to an int for illustration, but in my case > it's > a pointer to a structure); in addition, it uses an argument to return > another output (i.e. an argument is a pointer to an int that is filled > by the function). Here is my example: > > > int* test(int arg, int* error) { > int *res; > if(arg > 0) { > res = (int *) 1; > *error = 0; > } else { > res = NULL; > *error = 1; > } > return res; > } > > > I wrapped this with SWIG and applied a typemap on int* error to tell > that it is also an output. Here is my SWIG interface: > > > %include "typemaps.i" > > %apply int *OUTPUT {int* error}; > > %inline %{ > > int* test(int arg, int* error) { > int *res; > if(arg > 0) { > res = (int *) 1; > *error = 0; > } else { > res = NULL; > *error = 1; > } > return res; > } > > %} > > > So, when I use the module generated by SWIG with Python, I get this > behaviour: > > > >>> test(1) > [<Swig Object of type 'int *' at 0x1006bdde0>, 0] > >>> test(0) > 1 > > > It seems that when the function returns a NULL pointer, the output is > ignored and only the int* error output is used. > > Is it a bug or not? How can I fix this, such that when the result is > NULL I get "[None, 1]" in Python instead of just "1"? I can't > modify the > initial function. > > Thank you very much for your help, > > Regards, > > Simon Busard > > > PS: I checked the manual but found nothing. Please forgive me if the > answer was there but I missed it. > > You should write wrapper for that function. It's SWIG, baby. Yes, I > have the same problem (Some library function return result in two > output parameters (retval and via pointer in arg)), so, I have > [<result>, <result>] in stead of just <result>. So I asked this > mailing list for help, and people advice me to write a wrapper in .i > file, and then export wrapper instead of original function. > > > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and > threat landscape has changed and how IT managers can respond. > Discussions > will include endpoint security, mobile security and the latest in > malware > threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > _______________________________________________ > Swig-user mailing list > Swi...@li... > <mailto:Swi...@li...> > https://lists.sourceforge.net/lists/listinfo/swig-user > > > > > -- > Segmentation fault |
From: Josh W. <jos...@ac...> - 2012-08-22 11:51:48
|
Hi, The behavior you want is not supported by the typemaps in the file typemaps.i, so far as I know; to get this behavior you'll have to write your own output typemap in the interface file. The closest example I know of in the documentation is here: http://www.swig.org/Doc2.0/Python.html#Python_nn61 where the use of typemaps to return arguments is illustrated. In particular it shows this block of typemap code: // This tells SWIG to treat an double * argument with name 'OutValue' as // an output value. We'll append the value to the current result which // is guaranteed to be a List object by SWIG. %typemap(argout) double *OutValue { PyObject *o, *o2, *o3; o = PyFloat_FromDouble(*$1); if ((!$result) || ($result == Py_None)) { $result = o; } else { if (!PyTuple_Check($result)) { PyObject *o2 = $result; $result = PyTuple_New(1); PyTuple_SetItem(target,0,o2); } o3 = PyTuple_New(1); PyTuple_SetItem(o3,0,o); o2 = $result; $result = PySequence_Concat(o2,o3); Py_DECREF(o2); Py_DECREF(o3); } } int spam(double a, double b, double *OutValue, double *OutValue); You would need to write something similar, but omit the check beginning with: if ((!$result) || ($result == Py_None)) { and instead always concatenate the result of your "argout" typemap onto whatever is in $result. To be safe, you should have something like: if (!$result) $result = Py_None and then begin the code that is in the "else" block (i.e., you would NOT write that code inside of an else block; it would simply follow the line above). This change means that if $result is initially a NULL C pointer it is converted into the None object, but this should have already been done by the output typemap before the argout typemap is ever called. Probably better than modifying the above example is to look inside the generated wrapper C code; the function SWIG_Python_AppendOutput() is what SWIG is using to achieve the above behavior, and you should write your typemap to mimic that, but changing the logic that causes it to drop a "None" object off of a tuple or list of return values. That's all assuming that the behavior you describe is really appropriate for your wrapper; if a NULL pointer signifies an error (as in your example) the more Pythonic thing to do would be to write an exception handling typemap that uses NULL to signal the error, and then maybe looks in *error to decide what kind of exception to raise. There are examples of how to do that in the documentation. Cheers, Josh On Aug 22, 2012, at 1:47 AM, Simon Busard wrote: > Hello, > > I'm currently using SWIG to wrap a C library. I found a weird behaviour > and wanted to know if this is a bug or not, and how can I fix this. Here > is my problem: I have a function returning a pointer (I used in the > example below a pointer to an int for illustration, but in my case it's > a pointer to a structure); in addition, it uses an argument to return > another output (i.e. an argument is a pointer to an int that is filled > by the function). Here is my example: > > > int* test(int arg, int* error) { > int *res; > if(arg > 0) { > res = (int *) 1; > *error = 0; > } else { > res = NULL; > *error = 1; > } > return res; > } > > > I wrapped this with SWIG and applied a typemap on int* error to tell > that it is also an output. Here is my SWIG interface: > > > %include "typemaps.i" > > %apply int *OUTPUT {int* error}; > > %inline %{ > > int* test(int arg, int* error) { > int *res; > if(arg > 0) { > res = (int *) 1; > *error = 0; > } else { > res = NULL; > *error = 1; > } > return res; > } > > %} > > > So, when I use the module generated by SWIG with Python, I get this > behaviour: > > >>>> test(1) > [<Swig Object of type 'int *' at 0x1006bdde0>, 0] >>>> test(0) > 1 > > > It seems that when the function returns a NULL pointer, the output is > ignored and only the int* error output is used. > > Is it a bug or not? How can I fix this, such that when the result is > NULL I get "[None, 1]" in Python instead of just "1"? I can't modify the > initial function. > > Thank you very much for your help, > > Regards, > > Simon Busard > > > PS: I checked the manual but found nothing. Please forgive me if the > answer was there but I missed it. > > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and > threat landscape has changed and how IT managers can respond. Discussions > will include endpoint security, mobile security and the latest in malware > threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > _______________________________________________ > Swig-user mailing list > Swi...@li... > https://lists.sourceforge.net/lists/listinfo/swig-user -- Josh Willis Assistant Professor Email: jos...@ac... of Engineering & Physics Abilene Christian University Phone: (325) 674-2527 Box 27963 Fax: (325) 674-2146 Abilene, TX 79699-7963 Dept: (325) 674-2165 Foster Science Building Room 317 |
From: Simon B. <sim...@uc...> - 2012-08-22 12:12:27
|
Thank you very much for your help. I will investigate both solutions: writing my own typemap and using exceptions. Le Wed Aug 22 13:51:22 2012, Josh Willis a écrit : > Hi, > > The behavior you want is not supported by the typemaps in the file typemaps.i, so far as I know; to get this behavior you'll have to write your own output typemap in the interface file. > > The closest example I know of in the documentation is here: > > http://www.swig.org/Doc2.0/Python.html#Python_nn61 > > where the use of typemaps to return arguments is illustrated. In particular it shows this block of typemap code: > > // This tells SWIG to treat an double * argument with name 'OutValue' as > // an output value. We'll append the value to the current result which > // is guaranteed to be a List object by SWIG. > > %typemap(argout) double *OutValue { > PyObject *o, *o2, *o3; > o = PyFloat_FromDouble(*$1); > if ((!$result) || ($result == Py_None)) { > $result = o; > } else { > if (!PyTuple_Check($result)) { > PyObject *o2 = $result; > $result = PyTuple_New(1); > PyTuple_SetItem(target,0,o2); > } > o3 = PyTuple_New(1); > PyTuple_SetItem(o3,0,o); > o2 = $result; > $result = PySequence_Concat(o2,o3); > Py_DECREF(o2); > Py_DECREF(o3); > } > } > > int spam(double a, double b, double *OutValue, double *OutValue); > You would need to write something similar, but omit the check beginning with: > > if ((!$result) || ($result == Py_None)) { > and instead always concatenate the result of your "argout" typemap onto whatever is in $result. To be safe, you should have something like: > > if (!$result) $result = Py_None > > and then begin the code that is in the "else" block (i.e., you would NOT write that code inside of an else block; it would simply follow the line above). This change means that if $result is initially a NULL C pointer it is converted into the None object, but this should have already been done by the output typemap before the argout typemap is ever called. Probably better than modifying the above example is to look inside the generated wrapper C code; the function SWIG_Python_AppendOutput() is what SWIG is using to achieve the above behavior, and you should write your typemap to mimic that, but changing the logic that causes it to drop a "None" object off of a tuple or list of return values. > > That's all assuming that the behavior you describe is really appropriate for your wrapper; if a NULL pointer signifies an error (as in your example) the more Pythonic thing to do would be to write an exception handling typemap that uses NULL to signal the error, and then maybe looks in *error to decide what kind of exception to raise. There are examples of how to do that in the documentation. > > Cheers, > > Josh > > > > > On Aug 22, 2012, at 1:47 AM, Simon Busard wrote: > >> Hello, >> >> I'm currently using SWIG to wrap a C library. I found a weird behaviour >> and wanted to know if this is a bug or not, and how can I fix this. Here >> is my problem: I have a function returning a pointer (I used in the >> example below a pointer to an int for illustration, but in my case it's >> a pointer to a structure); in addition, it uses an argument to return >> another output (i.e. an argument is a pointer to an int that is filled >> by the function). Here is my example: >> >> >> int* test(int arg, int* error) { >> int *res; >> if(arg > 0) { >> res = (int *) 1; >> *error = 0; >> } else { >> res = NULL; >> *error = 1; >> } >> return res; >> } >> >> >> I wrapped this with SWIG and applied a typemap on int* error to tell >> that it is also an output. Here is my SWIG interface: >> >> >> %include "typemaps.i" >> >> %apply int *OUTPUT {int* error}; >> >> %inline %{ >> >> int* test(int arg, int* error) { >> int *res; >> if(arg > 0) { >> res = (int *) 1; >> *error = 0; >> } else { >> res = NULL; >> *error = 1; >> } >> return res; >> } >> >> %} >> >> >> So, when I use the module generated by SWIG with Python, I get this >> behaviour: >> >> >>>>> test(1) >> [<Swig Object of type 'int *' at 0x1006bdde0>, 0] >>>>> test(0) >> 1 >> >> >> It seems that when the function returns a NULL pointer, the output is >> ignored and only the int* error output is used. >> >> Is it a bug or not? How can I fix this, such that when the result is >> NULL I get "[None, 1]" in Python instead of just "1"? I can't modify the >> initial function. >> >> Thank you very much for your help, >> >> Regards, >> >> Simon Busard >> >> >> PS: I checked the manual but found nothing. Please forgive me if the >> answer was there but I missed it. >> >> ------------------------------------------------------------------------------ >> Live Security Virtual Conference >> Exclusive live event will cover all the ways today's security and >> threat landscape has changed and how IT managers can respond. Discussions >> will include endpoint security, mobile security and the latest in malware >> threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ >> _______________________________________________ >> Swig-user mailing list >> Swi...@li... >> https://lists.sourceforge.net/lists/listinfo/swig-user > > -- > Josh Willis > > Assistant Professor Email: jos...@ac... > of Engineering & Physics > > Abilene Christian University Phone: (325) 674-2527 > Box 27963 Fax: (325) 674-2146 > Abilene, TX 79699-7963 Dept: (325) 674-2165 > > Foster Science Building Room 317 > > > |
From: Johan H. <ha...@si...> - 2012-08-22 13:54:51
|
On 08/22/2012 02:12 PM, Simon Busard wrote: > Thank you very much for your help. I will investigate both solutions: > writing my own typemap and using exceptions. > > Le Wed Aug 22 13:51:22 2012, Josh Willis a écrit : >> Hi, >> >> The behavior you want is not supported by the typemaps in the file typemaps.i, so far as I know; to get this behavior you'll have to write your own output typemap in the interface file. >> >> The closest example I know of in the documentation is here: >> >> http://www.swig.org/Doc2.0/Python.html#Python_nn61 >> >> where the use of typemaps to return arguments is illustrated. In particular it shows this block of typemap code: >> >> // This tells SWIG to treat an double * argument with name 'OutValue' as >> // an output value. We'll append the value to the current result which >> // is guaranteed to be a List object by SWIG. >> >> %typemap(argout) double *OutValue { >> PyObject *o, *o2, *o3; >> o = PyFloat_FromDouble(*$1); >> if ((!$result) || ($result == Py_None)) { >> $result = o; >> } else { >> if (!PyTuple_Check($result)) { >> PyObject *o2 = $result; >> $result = PyTuple_New(1); >> PyTuple_SetItem(target,0,o2); >> } >> o3 = PyTuple_New(1); >> PyTuple_SetItem(o3,0,o); >> o2 = $result; >> $result = PySequence_Concat(o2,o3); >> Py_DECREF(o2); >> Py_DECREF(o3); >> } >> } You could the undocumented macro %append_output(o) which does the same as the above code, with less error prone coding :) Johan >> int spam(double a, double b, double *OutValue, double *OutValue); >> You would need to write something similar, but omit the check beginning with: >> >> if ((!$result) || ($result == Py_None)) { >> and instead always concatenate the result of your "argout" typemap onto whatever is in $result. To be safe, you should have something like: >> >> if (!$result) $result = Py_None >> >> and then begin the code that is in the "else" block (i.e., you would NOT write that code inside of an else block; it would simply follow the line above). This change means that if $result is initially a NULL C pointer it is converted into the None object, but this should have already been done by the output typemap before the argout typemap is ever called. Probably better than modifying the above example is to look inside the generated wrapper C code; the function SWIG_Python_AppendOutput() is what SWIG is using to achieve the above behavior, and you should write your typemap to mimic that, but changing the logic that causes it to drop a "None" object off of a tuple or list of return values. >> >> That's all assuming that the behavior you describe is really appropriate for your wrapper; if a NULL pointer signifies an error (as in your example) the more Pythonic thing to do would be to write an exception handling typemap that uses NULL to signal the error, and then maybe looks in *error to decide what kind of exception to raise. There are examples of how to do that in the documentation. >> >> Cheers, >> >> Josh >> >> >> >> >> On Aug 22, 2012, at 1:47 AM, Simon Busard wrote: >> >>> Hello, >>> >>> I'm currently using SWIG to wrap a C library. I found a weird behaviour >>> and wanted to know if this is a bug or not, and how can I fix this. Here >>> is my problem: I have a function returning a pointer (I used in the >>> example below a pointer to an int for illustration, but in my case it's >>> a pointer to a structure); in addition, it uses an argument to return >>> another output (i.e. an argument is a pointer to an int that is filled >>> by the function). Here is my example: >>> >>> >>> int* test(int arg, int* error) { >>> int *res; >>> if(arg > 0) { >>> res = (int *) 1; >>> *error = 0; >>> } else { >>> res = NULL; >>> *error = 1; >>> } >>> return res; >>> } >>> >>> >>> I wrapped this with SWIG and applied a typemap on int* error to tell >>> that it is also an output. Here is my SWIG interface: >>> >>> >>> %include "typemaps.i" >>> >>> %apply int *OUTPUT {int* error}; >>> >>> %inline %{ >>> >>> int* test(int arg, int* error) { >>> int *res; >>> if(arg > 0) { >>> res = (int *) 1; >>> *error = 0; >>> } else { >>> res = NULL; >>> *error = 1; >>> } >>> return res; >>> } >>> >>> %} >>> >>> >>> So, when I use the module generated by SWIG with Python, I get this >>> behaviour: >>> >>> >>>>>> test(1) >>> [<Swig Object of type 'int *' at 0x1006bdde0>, 0] >>>>>> test(0) >>> 1 >>> >>> >>> It seems that when the function returns a NULL pointer, the output is >>> ignored and only the int* error output is used. >>> >>> Is it a bug or not? How can I fix this, such that when the result is >>> NULL I get "[None, 1]" in Python instead of just "1"? I can't modify the >>> initial function. >>> >>> Thank you very much for your help, >>> >>> Regards, >>> >>> Simon Busard >>> >>> >>> PS: I checked the manual but found nothing. Please forgive me if the >>> answer was there but I missed it. >>> >>> ------------------------------------------------------------------------------ >>> Live Security Virtual Conference >>> Exclusive live event will cover all the ways today's security and >>> threat landscape has changed and how IT managers can respond. Discussions >>> will include endpoint security, mobile security and the latest in malware >>> threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ >>> _______________________________________________ >>> Swig-user mailing list >>> Swi...@li... >>> https://lists.sourceforge.net/lists/listinfo/swig-user >> >> -- >> Josh Willis >> >> Assistant Professor Email: jos...@ac... >> of Engineering & Physics >> >> Abilene Christian University Phone: (325) 674-2527 >> Box 27963 Fax: (325) 674-2146 >> Abilene, TX 79699-7963 Dept: (325) 674-2165 >> >> Foster Science Building Room 317 >> >> >> > > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and > threat landscape has changed and how IT managers can respond. Discussions > will include endpoint security, mobile security and the latest in malware > threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > _______________________________________________ > Swig-user mailing list > Swi...@li... > https://lists.sourceforge.net/lists/listinfo/swig-user > |