title: swig python interfacing to function using void **
body: <p>BACKGROUND. I have an API (third party provided) consisting of C header files and a shared library.  I have managed to create a shell script for the build environment, along with a simple interface file for swig.  I am trying to make this API accessible to an IPython environment such that I don't have to compile C code all the time to communicate with the associated hardware that leverages this API for I/O.  </p>
  
  <p>PROBLEM.  The first function call I need to do creates a board handle (some arbitrary "object" that is used for all other function calls in the C-side.  The function accepts a void **, assuming the underlying function is probably malloc-ing memory, has some sort of internal structure, and allows accessing this memory by some of the other functions.  Anyhow, I can't seem to properly interface to this from Python due to the lack of support for void * and receive a typeError.  </p>
  
  <p>The offending C code snippet, with typedef's/defines extracted from the underlying header files is:</p>
  
  <pre><code>    #define WD_PVOID  void*
      typedef WD_PVOID   WD_BOARD;
      typedef WD_UINT32  WD_RetCode;
      #define WD_EXPORT  extern
      #define WD_CHAR8  char
      #define WD_UINT32  unsigned int
      #---------------------------------------
      //prototype
      WD_EXPORT WD_RetCode wd_CreateBoardHandle( WD_BOARD *pBoardHandle, const WD_CHAR8  *pUrl );
  
      //interpreted prototype
      //extern unsigned int wd_CreateBoardHandle( void* *pBoardHandle, const char  *pUrl );
  </code></pre>
  
  <p>A third party provided provided example (written in C) uses the function as so (I removed superfluous stuff) :</p>
  
  <pre><code>  int main(int argc, char *argv [])
    {
       WD_RetCode rc;
       Vhdl_Example_Opts  cmdOpts = VHDL_EXAMPLE_DEFAULTS;
       char urlBoard[VHDL_SHORT_STRING_LENGTH];
       WD_BOARD           BoardHandle;
       sprintf(urlBoard, "/%s/%s/wildstar7/board%d", cmdOpts.hostVal, cmdOpts.boardDomain, cmdOpts.boardSlot);
  
       rc = wd_CreateBoardHandle(&amp;BoardHandle,urlBoard);
    }
  </code></pre>
  
  <p>and lastly, my watered down swig interface file (I have been trying swig typedef's and *OUTPUT with no success):</p>
  
  <pre><code>    %module wdapi
      %{
      #include "wd_linux_pci.h"
      #include "wd_types.h"
      #include "wd_errors.h"
      %}
      %import "wd_linux_pci.h"
      %import "wd_types.h"
      %import "wd_errors.h"
      %include &lt;typemaps.i&gt;
  
      WD_EXPORT WD_RetCode wd_CreateBoardHandle( WD_BOARD *pBoardHandle, const WD_CHAR8 *pUrl );
  
      WD_EXPORT WD_RetCode wd_OpenBoard( WD_BOARD  BoardHandle );
  </code></pre>
  
  <p>What I would like to be able to do is to call that function in python as so:</p>
  
  <pre><code>    rslt,boardHandle = wdapi.wd_CreateBoardHandle("/foo/bar/etc")
  </code></pre>
  
  <p>Please let me know if I can provide any other information and I greatly appreciate your help/guidance towards a solution!  I have spent days trying to review other similar issues posted.</p>
  
  <p>EDIT.  I manipulated some typedefs from other posts with similar issues.  I am able to now call the functions and receive both a value in rslt and boardHandle as an object; however, it appears the rslt value is gibberish.  Here is the new swig interface file (any thoughts as to the problem?):</p>
  
  <pre><code>      %module wdapi 
        %{
        #include "wd_linux_pci.h"
        #include "wd_types.h"
        #include "wd_errors.h"
        %}
  
        %import "wd_linux_pci.h"
        %import "wd_types.h"
        %import "wd_errors.h"
        %include &lt;python/typemaps.i&gt;
  
  
        %typemap(argout) WD_BOARD *pBoardHandle 
        {
          PyObject *obj = PyCObject_FromVoidPtr( *$1, NULL );
          $result = PyTuple_Pack(2, $result, obj);
        }
  
        %typemap(in,numinputs=0) WD_BOARD *pBoardHandle (WD_BOARD temp) 
        {
          $1 = &amp;temp;
        }
  
        %typemap(in) WD_BOARD {
          $1 = PyCObject_AsVoidPtr($input);
        }
  
  
        WD_EXPORT WD_RetCode wd_CreateBoardHandle( WD_BOARD *pBoardHandle, const WD_CHAR8 *pUrl );
  
        WD_EXPORT WD_RetCode wd_OpenBoard( WD_BOARD  BoardHandle );
  
        WD_EXPORT WD_RetCode wd_DeleteBoardHandle( WD_BOARD  BoardHandle );
  
        WD_EXPORT WD_RetCode wd_IsBoardPresent( const WD_CHAR8 *pUrl, WD_BOOL *OUTPUT );
  </code></pre>