1

Apologies for not being familiar with formatting on here...I've made some progress thanks to helpful replies and edited and removed my original question to be replaced by the current one.

My problem lies with converting a C struct or struct pointer to PyObject. There is no alternative to this because I am wrapping an existing C library whose callback requires a C struct pointer.

Following works but with limitations:

%module cain1
%{

  typedef struct {
    double price;
    int volume;
  } book_entry_t;

  typedef struct {

    char symbol[10];
    book_entry_t *book;

  } trade_t;

  typedef void (*CALLBACK)(trade_t trade);

  CALLBACK my_callback = 0;
  static PyObject *my_pycallback = NULL;

  static void bigSnake(trade_t trade)
  {
    PyObject *result;

    PyObject *d1;

    result =  PyEval_CallObject(my_pycallback,

                Py_BuildValue("(y#)",
                          (char*)&trade,
                          sizeof(trade_t)
                          )

                );

    Py_XDECREF(result);
    return /*void*/;

  }

  void test_cb (PyObject *callMe1) {
    trade_t d1;
    book_entry_t b1;
    b1.price = 123.45;
    b1.volume = 99;


    Py_XINCREF(callMe1);         /* Add a reference to new callback */
    my_pycallback = callMe1;     /* Remember new callback */

    strcpy (d1.symbol,"Gupta Ltd");
    d1.book = &b1;


    bigSnake(d1);

  }


%}


// Expose in python module..
typedef struct {
  double price;
  int volume;
} book_entry_t;

typedef struct {

  char symbol[10];
  book_entry_t *book;

} trade_t;


void test_cb(PyObject *callMe1);

and then triggering the callback from Python:

import cain1
import struct 

def dave(d1):
    N1,N2 = struct.unpack('10sP', d1)
    print ('\n   %s: %x' % (N1.decode() ,N2))

    price,volume = struct.unpack('di',N2)

    print (price,volume)

def main():
    cain1.test_cb(dave) 

main()

but I am unable to recover the book_entry_t strcut contents pointed to by trade_t....

I just feel this is all too convoluted since I have the pointer to structs and there must be a straightforward way for Python to use that without any fuss.

1
  • Where does gdb tell you it's segfaulting? Commented Aug 1, 2011 at 17:22

2 Answers 2

1

Py_BuildValue("(N)",details) expects a PyObject* (your "N" says so), and you pass it something very different. Try Py_BuildValue("(i)", details.index) instead, and change it to accomodate any changes in details_t.

Sign up to request clarification or add additional context in comments.

Comments

0

You're attempting to build a PyObject from a details_t struct. This isn't valid. Either pass the callback an integer (seems easier since details_t only has the one field) OR create a proper PyObject type. You can't blindly cast one type to another and expect it to work (a PyObject is more than just a pointer).

3 Comments

Yes, therein lies the problem. Passing an integer or string etc.
Yes that is problem. It works fine passing an integer or string,
Sorry... Yes works fine with integer, string etc. However I am wrapping an existing library and the callback requires a pointer to a C struct. I am puzzling over whether there is a painless way of converting a C struct to a PyObject without a lot of pain. result = PyEval_CallObject(my_pycallback, Py_BuildValue("(y#)", (char*)&trade, sizeof(trade_t) ) ); works where typedef struct { char symbol[10]; book_entry_t *book; } trade_t;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.