1

I am trying to make a python wrapper for a C library using ctypes. The library has functions which require a pointer to a structure to be passed, which acts as a handle for future calls.

This structure has pointers to another internal structure that further has pointers to other structures.

typedef struct varnam {
 char *scheme_file;
 char *suggestions_file;
 struct varnam_internal *internal;
} varnam;

The varnam_internal structure has pointers to an sqlite database and so forth

struct varnam_internal
{
 sqlite3 *db;
 sqlite3 *known_words;
 struct varray_t *r;
 struct token *v;
 ...
}

I tried ignoring the varnam_internal structure according to this SO answer. Something like

class Varnam(Structure):
 __fields__ = [("scheme_file",c_char_p),
 ("suggestions_file",c_char_p),("internal",c_void_p)]

But this does not seem to work because I think the library needs to allocate varnam_internal for functioning properly.

Should I implement all the dependent structures in python? Is ctypes suitable for wrapping libraries like this? I have read about alternatives like Cython but I have no experience with Cython so is this doable in it?

asked Sep 13, 2014 at 19:01

1 Answer 1

1

There's no reason define the varnam_internal structure in ctypes because you should have no need to access it. The library you're calling will allocate it regardless of whether you define the structure or not. Whatever problem you're encountering it's not because you didn't define the structure in ctypes.

Make sure you're calling varnam_init correctly. It uses pointers to pointers as arguments, which means you can't just use your Varnam class directly. You'll want do something like this:

from ctypes import *
class Varnam(Structure):
 __fields__ = [("scheme_file",c_char_p),
 ("suggestions_file",c_char_p),
 ("internal",c_void_p)]
varnam_ptr = POINTER(Varnam)
libvarnam = cdll.LoadLibrary("libvarnam.so") # on Linux
# libvarnam = cdll.libvarnam # on Windows
varnam_init = libvarnam.varnam_init
varnam_init.argtypes = [c_char_p, POINTER(varnam_ptr), POINTER(c_char_p)]
def my_varnam_init(scheme_file):
 handle = varnam_ptr()
 msg = c_char_p()
 r = varnam_init(scheme_file. handle.byref(), msg.byref())
 if r != 0:
 raise Exception(msg)
 return handle

The above code is completely untested, but shows you how you should be calling varnam_init.

answered Sep 14, 2014 at 2:00
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. You're right, I created a pointer of the Varnam class and used that for the function and not a pointer to a pointer. Now it works flawlessly.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.