1. Python CFFI
  2. Untitled project
  3. cffi
  4. Issues
Issue #79 new

no translation from Python2 "str" to C "const char*" in a struct field

Zooko O'Whielacronx
created an issue


Thank you for CFFI!

I have a struct defined like this:

typedef struct { size_t len; char* buf; } zstr;

and I pass instance of this struct by value in C, like this:

double unigram_prob_1(const zstr unigram, Pvoid_t* pUP);

CFFI is supposed to know what to do if I pass a Python "str" as an argument where a C "const char*" is required, and it is supposed to know what to do if I pass a Python tuple where a C struct is required, but putting the two together it does not know what to do if I pass Python2 "(len(mystr), mystr)" as the first argument to unigram_prob_1(). Is this a bug, or by-design? Thanks!

(It would be great for me if it would do what I want here. I'm currently rewriting all my C code to take two arguments -- len and buf -- wherever it used to take a zstr, and this is a hassle.)

Comments (3)

  1. Armin Rigo

    It's a bug I suppose. The reason is that ffi.new("zstr *", [len(mystr), mystr]) does not work, and that's correct. There is a special case only for function arguments to receive a "char[]" instead of a "char *", and thus a string is acceptable. But a "zstr" is a "zstr", and so the standard rules apply. While I see the point, I'm a bit unsure how exactly to fix it.

  2. Armin Rigo

    Trying to think more about this problem. If we allow recursively to give Python objects that are transformed into pointers and structs for the call, it raises an interesting question: should the following example work, or fail with a recursion error?

        struct node { struct node *next; };
        void f(struct node);
    my_node = {}
    my_node['next'] = [my_node]   # circular pointer
  3. Andrea Waite

    I don't like the idea that python objects automatically become pointers, because that implies they are magically allocated memory and become c objects implicitly.

    It could perhaps be supported by keeping a dictionary of already-converted objects using their python id() and making further references to them be to the already-created c objects. This means a cyclic graph traversal, not impossible. Desirable?

    Perhaps as a first cut, loops could be detected and rejected?

  4. Log in to comment