3

I have a legacy C/C++ struct like this (with many other members as well):

struct S {
  char one_name[MAX_LEN];
  char names[N_NAMES][MAX_LEN];
}

and a C function that creates these:

S *get_S(...)

I'd like to export S and names via swig so I can do this in python:

s = MyModule.get_S()
print s.one_name # I have this working
print s.names[1] # should print the 2nd string, this is harder

I assume I need some kind of typemap but I'm new to swig. I can do one_name with the wrapped_array template as in SWIG/python array inside structure, but I'm not sure how to extend that to an array of strings. I only need to read these strings from python (as above), not write them. I can do it with an accessor so the python would look like:

print s.get_name(i) # prints the ith name

but I'd prefer the array interface just because it's similar to the C one.

Community
  • 1
  • 1
GaryO
  • 5,873
  • 1
  • 36
  • 61
  • Is there a reason that you aren't using std::string? SWIG handles it automatically. – Oliver Feb 07 '14 at 22:05
  • @Schollii: I can't change the underlying interface I'm wrapping; it's ancient C code. If I need to I can write an accessor function though instead of exposing the string array directly. I was just hoping I could expose it in a pythonic way, yet as similar to the existing C code as possible so it would be familiar to users. – GaryO Feb 08 '14 at 23:22

1 Answers1

1

If you only need to read them from python, then a quick solution is to create an adapter class that uses std::strings, and an adapter function. This all goes in the .i file via %inline, you'll also need %rename and probably %ignore. Example,

%ignore(S)
%rename(S) Swrap
%rename(get_S) get_SWrap
%newobject get_Swrap

%inline %{
struct Swrap
{
     inline Swrap(S* s): one_name(s.one_name) 
     {
          for (i=0; i<N_NAMES; ++i)
               names[i] = s.names[i];
          // no longer need s:
          delete s; 
     }

     string one_name;
     string names[N_NAMES];    
};

Swrap* get_Swrap() {
    return new Swrap(get_S());
}
%}
Oliver
  • 27,510
  • 9
  • 72
  • 103
  • If I understand your solution, I think I wasn't clear. When I said I only need to read the strings, I meant read from python (my S struct is created and managed on the C side). Your solution works for strings that are read-only on the C side. Maybe there's a similar idea that works the other way though, I'll think about it more. I'm learning that Swig has lots of hooks for replacing just about anything. – GaryO Feb 10 '14 at 21:38
  • In your code, you create an S, then modify its data members. Do you need to do more than that, like pass it to an exported C++ function that modifies data member? Can you please extend your question with examples of operations you want to do from python, this will help a lot. – Oliver Feb 10 '14 at 22:18
  • I updated the question, hope it makes more sense now. – GaryO Feb 10 '14 at 22:33
  • I updated my answer. Note that %extend is very powerful and might make this even simpler. – Oliver Feb 12 '14 at 02:36
  • @garyo looks like you accepted, but no upvote; still not clear, or other reason? – Oliver Feb 16 '14 at 13:33
  • In my real case, I won't be able to make a simple copy of the original, since the underlying object is more dynamic, but this does point me in the right direction -- thanks! – GaryO Feb 17 '14 at 15:48