Kannan
Kannan

Reputation: 551

Python ctype: char array to c function is not getting updated when the c function writes values to it

Here is my C code:

//int MyFunc(char* res); -> This is the definition of C function
char data[4096];  
MyFunc(data);
printf("Data is : %s\n", data);

The data variable is updated by the C function. I used bytearray in Python to pass the variable as argument but the updated array is not reflecting. Any working code sample is much appreciated.

EDIT: I am using Python 3.7. My Python code:

data = bytearray(b'1234567890')
str_buffer = create_string_buffer(bytes(data), len(data))
print(MyFunc(str_buffer))
print(str_buffer.value) #Output: b''

str_buffer does not contain the values updated by MyFunc(). Calling MyFunc() from C# using the below signature works for me. I am looking for a Python 3.7 equivalent of it.

[DllImport("mydll.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int MyFunc(StringBuilder data);

Upvotes: 3

Views: 345

Answers (1)

A bytearray isn't the right way to pass a char * to a C function. Use create_string_buffer instead. Also, len(data) is an off-by-one error that results in a null terminator not being present, so either stick a + 1 on that or remove it, as the default length is right. Here's a minimal working example. First, a C function that turns every letter uppercase, and returns the number of letters that were already uppercase:

#include <ctype.h>

int MyFunc(char* res) {
    int i = 0;
    while(*res) {
        if(isupper(*res)) {
            ++i;
        } else {
            *res = toupper(*res);
        }
        ++res;
    }
    return i;
}

I compiled it with gcc -fPIC -shared upstring.c -o upstring.so. Since you're on Windows, you'll have to adapt this.

Now, some Python that calls it:

from ctypes import *
upstring = CDLL("./upstring.so") # Since you're on Windows, you'll have to adapt this too.
data = bytearray(b'abc12DEFGHI')
str_buffer = create_string_buffer(bytes(data)) # Note: using len(data) would be an off-by-one error that would lose the null terminator, so either omit it or use len(data)+1
print(upstring.MyFunc(str_buffer)) # prints 6
print(str_buffer.value) # prints b'ABC12DEFGHI'

Upvotes: 3

Related Questions