Note that there are some explanatory texts on larger screens.

plurals
  1. POC to Python via SWIG: can't get void** parameters to hold their value
    primarykey
    data
    text
    <p>I have a C interface that looks like this (simplified):</p> <pre><code>extern bool Operation(void ** ppData); extern float GetFieldValue(void* pData); extern void Cleanup(p); </code></pre> <p>which is used as follows:</p> <pre><code>void * p = NULL; float theAnswer = 0.0f; if (Operation(&amp;p)) { theAnswer = GetFieldValue(p); Cleanup(p); } </code></pre> <p>You'll note that Operation() allocates the buffer p, that GetFieldValue queries p, and that Cleanup frees p. I don't have any control over the C interface -- that code is widely used elsewhere.</p> <p>I'd like to call this code from Python via <a href="http://www.swig.org/" rel="nofollow noreferrer">SWIG</a>, but I was unable to find any good examples of how to pass a pointer to a pointer -- and retrieve its value.</p> <p>I think the correct way to do this is by use of typemaps, so I defined an interface that would automatically dereference p for me on the C side:</p> <pre><code>%typemap(in) void** { $1 = (void**)&amp;($input); } </code></pre> <p>However, I was unable to get the following python code to work:</p> <pre><code>import test p = None theAnswer = 0.0f if test.Operation(p): theAnswer = test.GetFieldValue(p) test.Cleanup(p) </code></pre> <p>After calling test.Operation(), p always kept its initial value of None. </p> <p>Any help with figuring out the correct way to do this in SWIG would be much appreciated. Otherwise, I'm likely to just write a C++ wrapper around the C code that stops Python from having to deal with the pointer. And then wrap <em>that</em> wrapper with SWIG. Somebody stop me!</p> <p>Edit:</p> <p>Thanks to <a href="https://stackoverflow.com/users/7161/jorenko">Jorenko</a>, I now have the following SWIG interface:</p> <pre><code>% module Test %typemap (in,numinputs=0) void** (void *temp) { $1 = &amp;temp; } %typemap (argout) void** { PyObject *obj = PyCObject_FromVoidPtr(*$1, Cleanup); $result = PyTuple_Pack(2, $result, obj); } %{ extern bool Operation(void ** ppData); extern float GetFieldValue(void *p); extern void Cleanup(void *p); %} %inline %{ float gfv(void *p){ return GetFieldValue(p);} %} %typemap (in) void* { if (PyCObject_Check($input)) { $1 = PyCObject_AsVoidPtr($input); } } </code></pre> <p>The python code that uses this SWIG interface is as follows:</p> <pre><code>import test success, p = test.Operation() if success: f = test.GetFieldValue(p) # This doesn't work f = test.gvp(p) # This works! test.Cleanup(p) </code></pre> <p>Oddly, in the python code, test.GetFieldValue(p) returns gibberish, but test.gfv(p) returns the correct value. I've inserting debugging code into the typemap for void*, and both have the same value of p! The call Any ideas about that?</p> <p><strong>Update:</strong> I've decided to use ctypes. MUCH easier.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload