5

I have an array of strings in Python 2.7, which I would like to pass to a C function via ctypes:

unsigned int SetParams(unsigned int count, const char **params)

So I can define the parameters in python:

import ctypes as ct
lib = ct.cdll.LoadLibrary('...')
lib.SetParams.restype  = ct.c_uint
lib.SetParams.argtypes = [ct.c_uint, ct.POINTER(ct.c_char_p)]

but now when I am given a set of params in a Python function, which I would like to use in the above library call, how do I actually call it? I am thinking something like this:

def setParameters(strParamList):
    numParams    = len(strParamList)
    strArrayType = ct.c_char_p * numParams
    strArray     = strArrayType()
    for i, param in enumerate(strParamList):
        strArray[i] = param
    lib.SetParams(numParams, strArray)

I am just starting with ctypes and wondering if there is a more automated way to do this? Also is the assignment strArray[i] = param actually reallocating? If so, this seems quite expensive -- is there a way to do this just pointing the string pointers to Python-allocated buffers, or they are not NULL-terminated?

UPDATE I did look through a couple related questions, but could not find a direct one to deal with the same issues. Thank you very much

1
  • For 'more automated' you might want to take a look at Cython. Commented Dec 6, 2016 at 18:22

2 Answers 2

1

You think correctly. That code works. Call with, for example:

setParameters(['abc','def','ghi'])

I haven't looked at the source, but ctypes on Python 2.7 (32-bit) does pass the internal Python buffer (tested by modifying the passed string in the C function and printing it after the call in Python), which is why you should only pass Python strings as above to functions that take const char* or at least are known not to modify the string. Since Python strings are immutable writing to them under C is a no-no. Use ctypes.create_string_buffer to create a writable string to pass to non-const char*.

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

Comments

1

I needed to make the following adjustments to the for loop in the setParameters python function

for i, param in enumerate(strParamList):
   if isinstance(param, bytes):
      strArray[i] = c_char_p(param)
   else:
      strArray[i] = c_char_p(param.encode('utf-8'))

This worked if the array argument to setParameters was [b'abc', b'def'] or ['abc','def'].

Comments

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.