from embedc import C a=[1,4,9] result = C(""" for (int i=0; i<3; i++) { sum += a[i]*a[i]; } return sum; """) print result
The example above accesses a Python array and computes the sum of the squares. Notice how "a" is accessed directly. In this example, when the C function is called, the module creates copies of all local and global variables (keeping the same names) in the C program, with the same type as the original. In the case above "a" is a C "int[]". At the end, the function copies back any changed C variables back to their Python source.
This also works within arrays, so in the follwing code, "a" would be [1,16,81]:
a=[1,4,9] C(""" for (int i=0; i<3; i++) { a[i] = a[i]*a[i]; } """) print a
Strings are converted to a "char *" C type. Changes to the string must be done with care to consider memory allocation problems. Consider the following code:
s='123' C('s="abc";')
"s" at then end would be "abc". Care must be taken when allocating memory for strings to avoid memory leaks. In the example above, there is no leak because "abc" is a const string.
The following code leaks memory:
s="123" C('s=strdup("abc")')
To solve this problem, use the GLOBAL and POST directives. GLOBAL declares global C variables and POST executes code after all the C variables have be saved in Python.
s="123" C(""" GLOBAL char *sav; sav=strdup("abc") s = sav POST free sav """)
GLOBAL creates a global C variable. POST is executed after the function returns and the variable transfers have occurred.
In the examples above, the code is compiled every time C is called. In some cases, particularly inside loops, it's helpful to compile the code once and reuse it. For example:
a=(1,6,4,3,2) for i in a: embedc.inline_c_precompile(""" IMPORT int i complex_calc(i) """)
When you call inline_c_precompile, the embedc module will read the original source code file, pick out the "inline_c_precompile" key word and read all the text between the triple-quotes. The text must be enclosed in triple-quotes, and the C/C++ code has to be in separate lines between them. This is done to speed up processing.
In addition, because the function has no run-time context when it is compiled, all variables must be defined with the IMPORT directive. The IMPORT keyword is followed by the type and the variable. Types are most C types (int, double, etc.) that ctypes supports. For strings, the type should be "string", not "char *" to differentiate from a Python array of chars.
Sometimes, it is useful to call a Python function from C. This is done by using the DEF directive. For example:
def myfunc(x, y): return x+y r = C(""" DEF int myfunc int int return myfunc(10,11); """)
The DEF keyword is followed by the return type, the function name, and the types of all the arguments. Note: I am considering making it more C-like by requiring parenthesis and commas as in "DEF int myfunc(int, int)" and may do so in the future if I need to support more complex types (like pointers and arrays). Right now only simple types (int, double, string) are supported.