From: Chih-Wei C. <me...@cw...> - 2015-02-14 03:53:36
|
Hi Bob, Thank you so much for the kindly example!!! It really helps me get some idea about typemap!! I'd like to make sure I get it correctly... (0) Where are the PyObject / Py_Non / PySequence_Check defined? Are they defined by SWIG? Are they kind of C's functions that work with Python? I couldn't find the correspond API in Go (i.e., GoObject or something else). (1) So, if I understand it correctly, typemap is somewhat like a C function, it takes value from Python and then output some C/C++ data structures, right? So I'm assuming almost all C/C++ syntax should be OK in the typemap block? (2) If, instead of const char **, I'd like to make the Go's Array map to C++'s std::vector, then I can do the similar thing, right? I only need to manipulate vector (say, push_back some values), right? (3) When will typemap(freearg) be called? Should I free the temporarily variable $1 here? Again, thanks so much for the help! -- Chih-Wei (Bert) 於 2015年2月14日 於 上午4:04:20, Bob Hood (bh...@co...) 寫: On 2/13/2015 10:27 AM, Chih-Wei Chang wrote: Hi, I'm wondering if there is any example or instruction on how I can pass Go's array to C++? I know this might relate to typemap. However, I'm not really familiar with that. So if there is any example, or if someone can give me a hint, it would be very appreciated. I'll give you something to chew on. I haven't checked all this code, so be wary about syntax errors. I don't know Go specifically or it's API. I can give you an example in Python, and the only real difference would be how you extract the incoming data from the scripting environment. Converting a scripting array (a "sequence" in Python) requires a target type if you plan to use a typemap. In this example, I'll assume you're receiving an array of strings. This means your target type would be "const char **". I'll also assume that the array requires a terminate NULL entry so the receive can iterate over it and know when the end has been reached. A typemap for that would look like: %typemap(in) const char ** { ... } (You can easily keep the difference between an "in" and and "out" typemap clear in your mind by always thinking that data is coming "in" from Python [or Go, in your case], or it is going "out" to Python [or Go] from your C/C++ code.) So, given the in-from-Python typemap above, you would add code to it to handle the conversion: %typemap(in) const char ** { $1 = NULL; if($input != Py_None) ... } Here we initialize the first input value, "const char **", represented by "$1" (if there were two inputs, then the second would be referenced using "$2" and so forth). Next a sanity check if performed on the value coming from the scripting language, "$input", to make sure it can be processed (in this case, "$input" is of type "PyObject *" since this is for Python). To keep the example simple, I'll assume that a "sequence" type is absolutely required (as opposed to adding code to handle single-value types), so I can update the typemap to reflect this design choice: %typemap(in) const char ** { $1 = NULL; if($input != Py_None && PySequence_Check($input)) ... } Now, I know that it's something I can work with. I check the size, allocate memory to hold the values, and then iterate over each element to transfer it into the C/C++ environment for subsequent processing: %typemap(in) const char ** { $1 = NULL; if($input != Py_None && PySequence_Check($input)) { int len = PySequence_Length($input); $1 = malloc(sizeof(char *) * (len + 1)); for(int i = 0;i < len;++i) { $1[i] = NULL; PyObject* item = PySequence_GetItem($input, i); if(PyString_Check(item)) { $1[i] = strdup(PyString_AsString(item)); } } $1[i] = NULL; // terminating entry } } If you know that the value in the "in" array will be stable for the duration of your processing, then you could just stuff the pointer value in to the array instead of allocating more memory: ... if(PyString_Check(item)) { $1[i] = PyString_AsString(item); } ... Finally, since you allocated memory in the "in" typemap, you'll want to add a typemap to hanldle freeing that memory after processing is complete: %typemap(freearg) const char ** { if($1) { // free the memory you allocated } } Hope that gets you moving ahead. |