MorphieBlossom
MorphieBlossom

Reputation: 1117

Converting python string object to c char* using ctypes

I am trying to send 2 strings from Python (3.2) to C using ctypes. This is a small part of my project on my Raspberry Pi. To test if the C function received the strings correctly, I place one of them in a text file.

Python code

string1 = "my string 1"
string2 = "my string 2"

# create byte objects from the strings
b_string1 = string1.encode('utf-8')
b_string2 = string2.encode('utf-8')

# send strings to c function
my_c_function(ctypes.create_string_buffer(b_string1),
              ctypes.create_string_buffer(b_string2))

C code

void my_c_function(const char* str1, const char* str2)
{
    // Test if string is correct
    FILE *fp = fopen("//home//pi//Desktop//out.txt", "w");
    if (fp != NULL)
    {
        fputs(str1, fp);
        fclose(fp);
    }

    // Do something with strings..
}

The problem

Only the first letter of the string appears in the text file.

I've tried many ways to convert the Python string object with ctypes.

With these conversions I keep getting the error "wrong type" or "bytes or integer address expected instead of str instance".

I hope someone can tell me where it goes wrong. Thanks in advance.

Upvotes: 41

Views: 61138

Answers (3)

MorphieBlossom
MorphieBlossom

Reputation: 1117

Thanks to @ErykSun the solution:

Python code

string1 = "my string 1"
string2 = "my string 2"

# create byte objects from the strings
b_string1 = string1.encode('utf-8')
b_string2 = string2.encode('utf-8')

# send strings to c function
my_c_function.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
my_c_function(b_string1, b_string2)

Upvotes: 50

Aksel
Aksel

Reputation: 533

I think you just need to use c_char_p() instead of create_string_buffer().

string1 = "my string 1"
string2 = "my string 2"

# create byte objects from the strings
b_string1 = string1.encode('utf-8')
b_string2 = string2.encode('utf-8')

# send strings to c function
my_c_function(ctypes.c_char_p(b_string1),
              ctypes.c_char_p(b_string2))

If you need mutable strings then use create_string_buffer() and cast those to c_char_p using ctypes.cast().

Upvotes: 20

user4113344
user4113344

Reputation:

Have you considered using SWIG? I haven't tried it myself but here's what it would look like, without changing your C source:

/*mymodule.i*/

%module mymodule
extern void my_c_function(const char* str1, const char* str2);

This would make your Python source as simple as (skipping compilation):

import mymodule

string1 = "my string 1"
string2 = "my string 2"
my_c_function(string1, string2)

Note I'm not certain .encode('utf-8') is necessary if your source file is already UTF-8.

Upvotes: 1

Related Questions