Import C++ Function into Python Program

Calling a python method from C/C++, and extracting its return value

As explained before, using PyRun_SimpleString seems to be a bad idea.

You should definitely use the methods provided by the C-API (http://docs.python.org/c-api/).

Reading the introduction is the first thing to do to understand the way it works.

First, you have to learn about PyObject that is the basic object for the C API. It can represent any kind of python basic types (string, float, int,...).

Many functions exist to convert for example python string to char* or PyFloat to double.

First, import your module :

PyObject* myModuleString = PyString_FromString((char*)"mytest");
PyObject* myModule = PyImport_Import(myModuleString);

Then getting a reference to your function :

PyObject* myFunction = PyObject_GetAttrString(myModule,(char*)"myabs");
PyObject* args = PyTuple_Pack(1,PyFloat_FromDouble(2.0));

Then getting your result :

PyObject* myResult = PyObject_CallObject(myFunction, args)

And getting back to a double :

double result = PyFloat_AsDouble(myResult);

You should obviously check the errors (cf. link given by Mark Tolonen).

If you have any question, don't hesitate. Good luck.

Calling C functions in Python

If I understand well, you have no preference for dialoging as c => python or like python => c.
In that case I would recommend Cython. It is quite open to many kinds of manipulation, specially, in your case, calling a function that has been written in Python from C.

Here is how it works (public api) :

The following example assumes that you have a Python Class (self is an instance of it), and that this class has a method (name method) you want to call on this class and deal with the result (here, a double) from C. This function, written in a Cython extension would help you to do this call.

cdef public api double cy_call_func_double(object self, char* method, bint *error):
if (hasattr(self, method)):
error[0] = 0
return getattr(self, method)();
else:
error[0] = 1

On the C side, you'll then be able to perform the call like so :

PyObject *py_obj = ....
...
if (py_obj) {
int error;
double result;
result = cy_call_func_double(py_obj, (char*)"initSimulation", &error);
cout << "Do something with the result : " << result << endl;
}

Where PyObject is a struct provided by Python/C API
After having caught the py_obj (by casting a regular python object, in your cython extension like this : <PyObject *>my_python_object), you would finally be able to call the initSimulation method on it and do something with the result.
(Here a double, but Cython can deal easily with vectors, sets, ...)

Well, I am aware that what I just wrote can be confusing if you never wrote anything using Cython, but it aims to be a short demonstration of the numerous things it can do for you in term of merging.

By another hand, this approach can take more time than recoding your Python code into C, depending on the complexity of your algorithms.
In my opinion, investing time into learning Cython is pertinent only if you plan to have this kind of needs quite often...

Hope this was at least informative...

Can we use C code in Python?

I want to invoke those C function or executables in python. Is that possible.

Yes, you can write C code that can be imported into Python as a module. Python calls these extension modules. You can invoke it from Python directly, an example from the documentation:

Python Code

import example
result = example.do_something()

C Code

static PyObject * example(PyObject *self)
{
// do something
return Py_BuildValue("i", result);
}

If I want the C code to be a library, which means I use it with #include and linkage of the *.o likely in python, how to do it or is that possible.

You build it as a shared library *.dll or *.so
You can also investigate using distutils to distribute your module.

If I write the C code into executable, which means it becomes a command, can I invoke it in python directly?

If you write a *.exe then you are doing the opposite (invoking Python from C). The method you choose (exe vs shared library) depends on if you want a "C program with some Python" or a "Python program with some C".

Also, I heard that python code can be compiled, does that mean we can execute the code without the source file? Are the output files binary files? Does it improve performance?

Python reads *.py files and compiles to *.pyc bytecode files when you run it. The bytecode is then run in the Python virtual machine. This means "executing the same file is faster the second time as recompilation from source to bytecode can be avoided." (from the Python glossary) So if you haven't edited your *.py files, it will run the *.pyc. You can distribute *.pyc files without *.py files, however they are not encrypted and can be reverse-engineered.

How do I connect a Python and a C program?

Use a pipe and popen

The easiest way to deal with this is probably to just use popen(3). The popen function is available in both Python and C and will connect a program of either language with the other using a pipe.

>>> import subprocess
>>> print args
['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"]
>>> p = subprocess.Popen(args)

Once you have the pipe, you should probably send yaml or json through it, though I've never tried to read either in C. If it's really a simple stream, just parse it yourself. If you like XML, I suppose that's available as well.

How to import a C file into python

To use c file according to docs you need to first compile C code and then use the compiled file in your code

here is the link.
Visit http://book.pythontips.com/en/latest/python_c_extension.html

How can I import an external C function into an IPython Notebook using Cython?

The %cython magic command probaby doesn't seem to do the trick.

The %cython magic command doesn't really do the task here. In order to compile this you need to also supply the *.c source file and that (as far as I'm aware) isn't allowed with %cython. (The source file for it indicates that it only uses the text entered in the cell as a source file.)

Wrap your C functions:

Before presenting a probable solution, let me point out that the .pyx file you have created doesn't actually wrap the C function order_spam automatically. You can have it automatically wrapped if you specify it as cpdef inside the cdef extern block (alternatively you could wrap it on your own outside the cdef extern block, this allows more flexibility).

I'll use a filename of cyspam.pyx for the Cython file:

cdef extern from "spam.c":
cpdef void order_spam(int tons)

Notice how I've prefixed the function declaration with cpdef, this instructs Cython to automatically wrap the function.

Use a setup.py script:

In order to have full control over the compilation process, you usually need to create a setup.py script that has all the required sources, include directories et cetera, specified.

Here's how the setup.py script should look like:

from distutils.core import setup, Extension
from Cython.Build import cythonize

# you specify the c source file in the sources list
ext = Extension('cyspam', sources = ['cyspam.pyx', 'spam.c'])
setup(name="C spam", ext_modules = cythonize([ext]))

You can either create a file like this via a simple text editor or via IPython with the %%writefile magic command. The setup.py script should of course be placed in the same directory as the cyspam.pyx and spam.c files.

Compile the files:

You can either open a terminal for this or use the %%bash command from IPython, either way does the trick. Issue the following command:

python setup.py build_ext --inplace 

--inplace places the generated .so file in the current directory.

After doing these you can easily import the file cyspam in Ipython and just call the wrapped C function:

Rounding up all commands from IPython:

All in all, if you want to do it only from IPython you'll issue the following commands:

In [1]: %%writefile setup.py
....: from distutils.core import setup, Extension
....: from Cython.Build import cythonize
....: ext = Extension('cyspam', sources = ['cyspam.pyx', 'spam.c'])
....: setup(name="C spam", ext_modules = cythonize([ext]))

In [2]: %%bash
...: python setup.py build_ext --inplace

In [3]: import cyspam

In [4]: cyspam.order_spam(1000)
You ordered 1000 ammount of spam!

As an alternative you could always create a .pyxbld file that specifies the needed arguments for pyximport.install(). This offers the same level of control but is most likely counter-intuitive for Python users who already have experience with using setup.py scripts.

See Related:

How can I set Cython compiler flags when using pyximport?



Related Topics



Leave a reply



Submit