E
Eric Frederich
I am attempting to automate the building of binding for a 3rd party library.
The functions I'm wrapping all return an integer of whether they
failed and output are passed as pointers.
There can be multiple return values.
So the code that I generate has a PyObject* called python__return_val
that I use for returning.
In the 'wrapped_foo' function below you see I build the return value
with Py_BuildValue and "OO" as the format.
For every output I have I do a C to Python conversion and add another
'O' to the format.
What I'm wondering is if I can use the same logic when wrapping
functions that only return one value like the wrapped_bar function
below.
So for multiples, I wind up doing this which is fine.
python__x = Py_BuildValue("s", x)
python__y = Py_BuildValue("s", y)
python__return_val = Py_BuildValue("OO", python__x, python__y);
But for single returns I do something like this....
I realize that the 2 lines below are pointless, but are they causing a
memory leak or problems with reference counting?
python__x = Py_BuildValue("s", x)
python__return_val = Py_BuildValue("O", python__x);
Are python__x and python__return_val the same object, a copy of the object?
Would python__x ever get garbage collected?
Should my code generator detect when there is only one output and not
go through the extra step?
Thanks,
~Eric
static PyObject *
wrapped_foo(PyObject *self, PyObject *args)
{
int wrapp_fail;
// C types
int x;
const char* some_str;
int* y;
char** abc;
// Python types
PyObject* python__return_val;
PyObject* python__y;
PyObject* python__abc;
// Get Python args
if (!PyArg_ParseTuple(args, "is", &x, &some_str))
return NULL;
// Wrapped Call
wrapp_fail = foo(x, some_str, &y, &abc);
if(wrapp_fail != 0){
return NULL;
}
// Convert output to Python types
python__y = Py_BuildValue("i", y)
python__abc = Py_BuildValue("s", abc)
// Build Python return value
python__return_val = Py_BuildValue("OO", python__y, python__abc);
// Memory free's
MEM_free(abc)
return python__return_val;
}
static PyObject *
wrapped_bar(PyObject *self, PyObject *args)
{
int wrapp_fail;
// C types
int a;
const char* b;
char** c;
// Python types
PyObject* python__return_val;
PyObject* python__c;
// Get Python args
if (!PyArg_ParseTuple(args, "is", &a, &b))
return NULL;
// Wrapped Call
wrapp_fail = bar(a, b, &c);
if(wrapp_fail != 0){
return NULL;
}
// Convert output to Python types
python__c = Py_BuildValue("s", c)
// Build Python return value
python__return_val = Py_BuildValue("O", python__c);
// Memory free's
MEM_free(c)
return python__return_val;
}
The functions I'm wrapping all return an integer of whether they
failed and output are passed as pointers.
There can be multiple return values.
So the code that I generate has a PyObject* called python__return_val
that I use for returning.
In the 'wrapped_foo' function below you see I build the return value
with Py_BuildValue and "OO" as the format.
For every output I have I do a C to Python conversion and add another
'O' to the format.
What I'm wondering is if I can use the same logic when wrapping
functions that only return one value like the wrapped_bar function
below.
So for multiples, I wind up doing this which is fine.
python__x = Py_BuildValue("s", x)
python__y = Py_BuildValue("s", y)
python__return_val = Py_BuildValue("OO", python__x, python__y);
But for single returns I do something like this....
I realize that the 2 lines below are pointless, but are they causing a
memory leak or problems with reference counting?
python__x = Py_BuildValue("s", x)
python__return_val = Py_BuildValue("O", python__x);
Are python__x and python__return_val the same object, a copy of the object?
Would python__x ever get garbage collected?
Should my code generator detect when there is only one output and not
go through the extra step?
Thanks,
~Eric
static PyObject *
wrapped_foo(PyObject *self, PyObject *args)
{
int wrapp_fail;
// C types
int x;
const char* some_str;
int* y;
char** abc;
// Python types
PyObject* python__return_val;
PyObject* python__y;
PyObject* python__abc;
// Get Python args
if (!PyArg_ParseTuple(args, "is", &x, &some_str))
return NULL;
// Wrapped Call
wrapp_fail = foo(x, some_str, &y, &abc);
if(wrapp_fail != 0){
return NULL;
}
// Convert output to Python types
python__y = Py_BuildValue("i", y)
python__abc = Py_BuildValue("s", abc)
// Build Python return value
python__return_val = Py_BuildValue("OO", python__y, python__abc);
// Memory free's
MEM_free(abc)
return python__return_val;
}
static PyObject *
wrapped_bar(PyObject *self, PyObject *args)
{
int wrapp_fail;
// C types
int a;
const char* b;
char** c;
// Python types
PyObject* python__return_val;
PyObject* python__c;
// Get Python args
if (!PyArg_ParseTuple(args, "is", &a, &b))
return NULL;
// Wrapped Call
wrapp_fail = bar(a, b, &c);
if(wrapp_fail != 0){
return NULL;
}
// Convert output to Python types
python__c = Py_BuildValue("s", c)
// Build Python return value
python__return_val = Py_BuildValue("O", python__c);
// Memory free's
MEM_free(c)
return python__return_val;
}