need assistance with C extesion

djw dwelch91 at
Tue Feb 11 18:24:12 CET 2003

  Hello all,

I am having some difficulty creating a C extension on RH8/Py2.2.1. I am 
trying to hand write a C wrapper to wrap an existing library that has an 
API that doesn't seem to be conducive to being made into a Python 
extension (I don't really have the option of changing the API).

The problem, I think, boils down to the fact that the API passes 
pointers to structs that contain pointers to functions.

My attempts to use SWIG on this have all failed.

Here is the essence of the API:

/* The structure that contains pointers to functions. */
struct ptalProvider_s {
     char *name;

     int sizeofDevice;
     int sizeofChannel;

     ptalDevice_t (*deviceOpen)(char *devname,int lenPrefix);
     void (*deviceConstructor)(ptalDevice_t dev,void *cbd);
     void (*deviceDestructor)(ptalDevice_t dev);
     void (*deviceDump)(ptalDevice_t dev,int level);
     int (*deviceGetDeviceIDString)(ptalDevice_t dev,
         char *buffer,int maxlen);
     int (*deviceGetPreviousDeviceIDString)(ptalDevice_t dev,
         char *buffer,int maxlen);

     void (*channelConstructor)(ptalChannel_t chan);
     void (*channelDestructor)(ptalChannel_t chan);
     void (*channelDump)(ptalChannel_t chan,int level);

     int (*channelIsOpen)(ptalChannel_t chan);
     int (*channelOpen)(ptalChannel_t chan);
     int (*channelClose)(ptalChannel_t chan);

     int (*channelSelect)(ptalChannel_t chan,int *pr,int *pw,int *px,
         struct timeval *timeout);

     int (*channelRead)(ptalChannel_t chan,char *buffer,int count);
     int (*channelWrite)(ptalChannel_t chan,char *buffer,int count);

     int (*pmlOpen)(ptalDevice_t dev);
     int (*pmlClose)(ptalDevice_t dev);
     int (*pmlGet)(ptalPmlObject_t obj,ptalPmlObject_t next);
     int (*pmlSet)(ptalPmlObject_t obj);
     int (*pmlSetTrap)(ptalPmlObject_t obj,int enable);
     int (*pmlServiceTraps)(ptalDevice_t dev);

/* A pointer type for the above structure */
typedef struct ptalProvider_s *ptalProvider_t;

/* A representative function declaration in the API. */
int ptalDeviceEnumerate(ptalProvider_t provider, ptalDeviceEnumerate_f 
callback,void *cbd);

/* Another structure that is used. */
struct ptalDevice_s {
     ptalDevice_t prev,next;

     ptalProvider_t provider;
     char *devname;        /* dynamically allocated */
     int lenPrefix;        /* length of provider name and colon(s) */
     void *appInfo;        /* application private data */
     ptalFile_t configFile;

     ptalChannel_t firstChannel;
     ptalChannel_t lastChannel;

     ptalChannel_t pmlChannel;
     ptalPmlObject_t firstPmlObject;
     ptalPmlObject_t lastPmlObject;

/* Pointer to a device struct */
typedef struct ptalDevice_s *ptalDevice_t;

/* Sample APIs for devices */
ptalDevice_t ptalDeviceOpen(char *name);
int ptalDeviceClose(ptalDevice_t dev);

In this API, there are 2 additional structures and cooresponding 
(pointer) types (channels and pmlobjects) that are passed back and 
forth. The C code that I have seen that uses this API defines variables 
that are of type "ptalDevice_t" (for example) and then passes it into a 
function. Because of the embedded C function pointers, SWIG seems to 
balk at this. (And I don't know how to hand code it either).

I have a couple of ideas on how to handle this, but they both seem 
pretty kludgy.

First, I though, maybe just declare a one or a few global instances of 
each _t pointer that I need in the C wrapper code. This would require 
that some severe limitations be placed on the code, for example, only 1 
device can be used at a time (cooresponding to the 1 instance declared 
in the C wrapper) or n number of channels available. This is too 
restrictive for what I need, though.

So, I thought, maybe there needs to be some sort of storage and access 
mechanism in the C wrapper (STL maps, maybe?) and a way of referring to 
them, like handles or descriptors. I would have to add some API kruft to 
create and destroy the handles so that the underlaying C objects will be 
created and destroyed. Maybe that would work, but seems pretty messy and 
has the potential to hide memory leaks and the like.

I still don't understand if there is a way to use "opaque" pointers to 
the structures and have the pointers "flow" through Python code 
unaffected. If there is, I don't know how to appoach it.

Are there other ways to handle this that I can't seem to conjure up?

Any and all help is much appreciated.



PS. Yes, I have done my homework: searched with Google, Google Groups, 
consulted every Python book I own, and haven't found the answer.

More information about the Python-list mailing list