1

In C I have a function that expects array of unsigned chars

void writedata(unsigned char *datapos, int datanum)

I would like to pass a standard string from Python instead

writedata = parallel.writedata
writedata.argtypes = [POINTER(c_ubyte), c_int]

a = "test string"
writedata(a, 11)

As far as I understand, string is actually an array of bytes/chars, and a is a pointer. However, ctypes disagrees:

ctypes.ArgumentError: argument 2: <type 'exceptions.TypeError'>: expected LP_c_ubyte instance instead of str

How can I get "real" pointer from a string?

EDIT: David Cullen provided a solution that takes string pointer as a parameter:

writedata.argtypes = [c_char_p, c_int]

That's fine, but I would like to supply both byte arrays and strings to the function. This means that this should also work

ll = [0,1,2,3,4,5,6,7]
uints = (c_ubyte*8)(*ll)
writedata(uints, 8)

I am curious why I can't do both, because in terms of memory I think byte arrays and strings should be the same? Perhaps this is all about pointer conversions?

I also tried make two ctypes connections to the same C function, and this does not work.

SOLUTION: I have reformulated the question and received the best answer here:

https://stackoverflow.com/a/64838842/2957687

8
  • I think you may find usefull this question : click me Commented Nov 12, 2020 at 19:44
  • @IkarusDeveloper It must be ctypes. I already written a huge program and all other Python <-> C communication is done by ctypes Commented Nov 12, 2020 at 19:58
  • 1
    "As far as I understand, string is actually an array of bytes/chars" - a C string is, but not a Python string. A Python string is an abstract sequence of Unicode code points, which may have multiple different in-memory representations. Commented Nov 12, 2020 at 22:28
  • @user2357112supportsMonica Fair argument. What about if I know there are only ASCII characters, or if I put b in front, i.e. b"test string"? Commented Nov 12, 2020 at 22:49
  • @Pygmalion: Putting a b in front makes it bytes, not str, so it should work. Commented Nov 12, 2020 at 23:10

1 Answer 1

1

We can use the same function if we convert strings to match the required argument types:

def writedata(value):
    if isinstance(value, str):
        value = (ctypes.c_ubyte * len(value)) (*bytearray(value))
    writedataf(value, len(value))

To test my theory, I created a very simple library:

#include <stdio.h>

void writedata(unsigned char *datapos, int datanum) {
    for (int index = 0; index < datanum; index++) {
        putchar(datapos[index]);
    }
    putchar('\n');
}

I created a shared library for macos using

clang -Wall -Werror -shared -fpic main.c -o libwritedata.so

I coped the shared library to /usr/local/lib and created this Python script:

import ctypes

writedataf = ctypes.CDLL('/usr/local/lib/libwritedata.so').writedata
writedataf.argtypes = [ctypes.POINTER(ctypes.c_ubyte), ctypes.c_int]

def writedata(value):
    if isinstance(value, str):
        value = (ctypes.c_ubyte * len(value)) (*bytearray(value))
    writedataf(value, len(value))

x = "a short string"
writedata(x)
uints = (ctypes.c_ubyte * len(x)) (*bytearray(x))
writedata(uints)

Output

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

4 Comments

+1 Uh, oh, it works, but I am sometimes accessing the same function with actual char/byte arrays, i.e. uints = (c_ubyte*8)(*name_of_list), writedata(uints, 8). Can I have both?
@Pygmalion I modifed the script to handle both data types.
I really appreciate the effort, but this will not work for me, because I malloc different structs in the C library that have to be available for all functions... If I load several instances of the same C library this structs won't be visible.
@Pygmalion I modified the script so that the library is only loaded once.

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.