create a python module with C and Python code - python

I have a small python module I have created with the Python C API which I call mycore.
I have also created some utility scripts in Python which are related.
How can I put both in the same module namespace? I know I can call Python code from my C code but surely there is an easier way to do that.
Thanks

The obvious way is by making mycore a package. Create a mycore/__init__.py that imports both the C part, typically named something like _mycore, and the Python part:
from _mycore import *
from _mycorepy import *
In the same directory you'd have a _mycore.so and _mycorepy.py.
Another way to mix Python and C code is by invoking PyRun_String on the embedded Python. This might be what you mean by I know I can call Python code from my C code..., but just in case, here is a simple example with the potentially tricky refcounting details:
PyObject *get_factory()
{
PyObject *g, *runret, *factory;
// prepare a dictionary for the module to run in
g = Py_BuildValue("{s:O}", "__builtins__", PyEval_GetBuiltins());
if (!g)
return NULL;
// run Python code in the dictionary -- the code may import modules, etc.
runret = PyRun_String("\
def factory():\n\
return 42\n", Py_file_input, g, NULL);
Py_XDECREF(runret);
if (!runret) {
Py_DECREF(g);
return NULL;
}
Py_DECREF(runret);
// pick the stuff you care about from the dictionary and return it
factory = PyDict_GetItemString(g, "factory");
Py_INCREF(factory);
Py_DECREF(g);
return factory;
}

OK, this worked for me. My circumstances may be different. My C module was built internally and provided to my embedded Python with a call to PyImport_AppendInittab().
But I still had some accompanying Python code that I wanted associated with the same namespace.
So I got it working by naming my C code _mygadget and the Python file mygadget.py. For the first line of mygadget.py I wrote:
from _mygadget import *
This seems to work. I don't know what would happen if I had a Python method and C call with the same name. I am avoiding that at present.

Related

How to reload python module that is build with c++ source code using pybind11

I am using the first step example in pybind11's documentation
#include <pybind11/pybind11.h>
int add(int i, int j)
{
return i + j;
}
PYBIND11_MODULE(example, m)
{
m.doc() = "pybind11 example plugin"; // optional module docstring
m.def("add", &add, "A function which adds two numbers");
}
everything works fine, i can use it in python shell:
import example
example.add(2, 3) #returns 5
Now i made a simple change to use float instead of int for input for add(), everything compiles. and i want to reload the module example so i can test the new float based add(). However, i can not figure out a way to reload the example module. importlib.reload does not work, %autorelaod 2 in IPython does not work either.
both approached tested to work with pure python based modules, but not the c++ and pybind11 based modules.
Did I miss anything here? or it ought to be like this?
UPDATE: seems it is a known issue related to How to Reload a Python3 C extension module?
Python's import mechanism will never dlclose() a shared library. Once
loaded, the library will stay until the process terminates.
pybind11 module and ctypes module seems to share the same traits here regarding how the module is loaded/imported.
Also quote from https://github.com/pybind/pybind11/issues/2511:
The way C extensions are loaded by Python does not allow them to be
reloaded (in contract to Python modules, where the Python code can
just be reloaded and doesn't refer to a dynamically loaded library)
I now just wonder if there is a method to wrap this up in a more convenient way for reloading the module. E.g., spawn a subprocess for a new python shell that copies all C extensions related variable/module, and substitute the original one.
Its seems no way straightforward. Since it's possible to manage standard shared library by manually dlopen() & dlclose(), you can change your PYBIND11_MODULE to a pre-defined function like
void __bind_module(void *bind_) {
typedef void (*binder_t)(const char *, py::cpp_function);
auto bind = (binder_t) bind_;
bind("add", add);
}
and then write a manager module to attach/detach those libraries. Something like importlib from yourself.

how to include shared object in python [duplicate]

I'm just getting started with ctypes and would like to use a C++ class that I have exported in a dll file from within python using ctypes.
So lets say my C++ code looks something like this:
class MyClass {
public:
int test();
...
I would know create a .dll file that contains this class and then load the .dll file in python using ctypes.
Now how would I create an Object of type MyClass and call its test function? Is that even possible with ctypes? Alternatively I would consider using SWIG or Boost.Python but ctypes seems like the easiest option for small projects.
Besides Boost.Python(which is probably a more friendly solution for larger projects that require one-to-one mapping of C++ classes to python classes), you could provide on the C++ side a C interface. It's one solution of many so it has its own trade offs, but I will present it for the benefit of those who aren't familiar with the technique. For full disclosure, with this approach one wouldn't be interfacing C++ to python, but C++ to C to Python. Below I included an example that meets your requirements to show you the general idea of the extern "c" facility of C++ compilers.
//YourFile.cpp (compiled into a .dll or .so file)
#include <new> //For std::nothrow
//Either include a header defining your class, or define it here.
extern "C" //Tells the compile to use C-linkage for the next scope.
{
//Note: The interface this linkage region needs to use C only.
void * CreateInstanceOfClass( void )
{
// Note: Inside the function body, I can use C++.
return new(std::nothrow) MyClass;
}
//Thanks Chris.
void DeleteInstanceOfClass (void *ptr)
{
delete(std::nothrow) ptr;
}
int CallMemberTest(void *ptr)
{
// Note: A downside here is the lack of type safety.
// You could always internally(in the C++ library) save a reference to all
// pointers created of type MyClass and verify it is an element in that
//structure.
//
// Per comments with Andre, we should avoid throwing exceptions.
try
{
MyClass * ref = reinterpret_cast<MyClass *>(ptr);
return ref->Test();
}
catch(...)
{
return -1; //assuming -1 is an error condition.
}
}
} //End C linkage scope.
You can compile this code with
gcc -shared -o test.so test.cpp
#creates test.so in your current working directory.
In your python code you could do something like this (interactive prompt from 2.7 shown):
>>> from ctypes import cdll
>>> stdc=cdll.LoadLibrary("libc.so.6") # or similar to load c library
>>> stdcpp=cdll.LoadLibrary("libstdc++.so.6") # or similar to load c++ library
>>> myLib=cdll.LoadLibrary("/path/to/test.so")
>>> spam = myLib.CreateInstanceOfClass()
>>> spam
[outputs the pointer address of the element]
>>> value=CallMemberTest(spam)
[does whatever Test does to the spam reference of the object]
I'm sure Boost.Python does something similar under the hood, but perhaps understanding the lower levels concepts is helpful. I would be more excited about this method if you were attempting to access functionality of a C++ library and a one-to-one mapping was not required.
For more information on C/C++ interaction check out this page from Sun: http://dsc.sun.com/solaris/articles/mixing.html#cpp_from_c
The short story is that there is no standard binary interface for C++ in the way that there is for C. Different compilers output different binaries for the same C++ dynamic libraries, due to name mangling and different ways to handle the stack between library function calls.
So, unfortunately, there really isn't a portable way to access C++ libraries in general. But, for one compiler at a time, it's no problem.
This blog post also has a short overview of why this currently won't work. Maybe after C++0x comes out, we'll have a standard ABI for C++? Until then, you're probably not going to have any way to access C++ classes through Python's ctypes.
The answer by AudaAero is very good but not complete (at least for me).
On my system (Debian Stretch x64 with GCC and G++ 6.3.0, Python 3.5.3) I have segfaults as soon has I call a member function that access a member value of the class.
I diagnosticated by printing pointer values to stdout that the void* pointer coded on 64 bits in wrappers is being represented on 32 bits in Python. Thus big problems occurs when it is passed back to a member function wrapper.
The solution I found is to change:
spam = myLib.CreateInstanceOfClass()
Into
Class_ctor_wrapper = myLib.CreateInstanceOfClass
Class_ctor_wrapper.restype = c_void_p
spam = c_void_p(Class_ctor_wrapper())
So two things were missing: setting the return type to c_void_p (the default is int) and then creating a c_void_p object (not just an integer).
I wish I could have written a comment but I still lack 27 rep points.
Extending AudaAero's and Gabriel Devillers answer I would complete the class object instance creation by:
stdc=c_void_p(cdll.LoadLibrary("libc.so.6"))
using ctypes c_void_p data type ensures the proper representation of the class object pointer within python.
Also make sure that the dll's memory management be handled by the dll (allocated memory in the dll should be deallocated also in the dll, and not in python)!
I ran into the same problem. From trial and error and some internet research (not necessarily from knowing the g++ compiler or C++ very well), I came across this particular solution that seems to be working quite well for me.
//model.hpp
class Model{
public:
static Model* CreateModel(char* model_name) asm("CreateModel"); // static method, creates an instance of the class
double GetValue(uint32_t index) asm("GetValue"); // object method
}
#model.py
from ctypes import ...
if __name__ == '__main__':
# load dll as model_dll
# Static Method Signature
fCreateModel = getattr(model_dll, 'CreateModel') # or model_dll.CreateModel
fCreateModel.argtypes = [c_char_p]
fCreateModel.restype = c_void_p
# Object Method Signature
fGetValue = getattr(model_dll, 'GetValue') # or model_dll.GetValue
fGetValue.argtypes = [c_void_p, c_uint32] # Notice two Params
fGetValue.restype = c_double
# Calling the Methods
obj_ptr = fCreateModel(c_char_p(b"new_model"))
val = fGetValue(obj_ptr, c_int32(0)) # pass in obj_ptr as first param of obj method
>>> nm -Dg libmodel.so
U cbrt#GLIBC_2.2.5
U close#GLIBC_2.2.5
00000000000033a0 T CreateModel # <----- Static Method
U __cxa_atexit#GLIBC_2.2.5
w __cxa_finalize#GLIBC_2.2.5
U fprintf#GLIBC_2.2.5
0000000000002b40 T GetValue # <----- Object Method
w __gmon_start__
...
...
... # Mangled Symbol Names Below
0000000000002430 T _ZN12SHMEMWrapper4HashEPKc
0000000000006120 B _ZN12SHMEMWrapper8info_mapE
00000000000033f0 T _ZN5Model12DestroyModelEPKc
0000000000002b20 T _ZN5Model14GetLinearIndexElll
First, I was able to avoid the extern "C" directive completely by instead using the asm keyword which, to my knowledge, asks the compiler to use a given name instead of the generated one when exporting the function to the shared object lib's symbol table. This allowed me to avoid the weird symbol names that the C++ compiler generates automatically. They look something like the _ZN1... pattern you see above. Then in a program using Python ctypes, I was able to access the class functions directly using the custom name I gave them. The program looks like fhandle = mydll.myfunc or fhandler = getattr(mydll, 'myfunc') instead of fhandle = getattr(mydll, '_ZN12...myfunc...'). Of course, you could just use the long name; it would make no difference, but I figure the shorter name is a little cleaner and doesn't require using nm to read the symbol table and extract the names in the first place.
Second, in the spirit of Python's style of object oriented programming, I decided to try passing in my class' object pointer as the first argument of the class object method, just like when we pass self in as the first method in Python object methods. To my surprise, it worked! See the Python section above. Apparently, if you set the first argument in the fhandle.argtypes argument to c_void_ptr and pass in the ptr you get from your class' static factory method, the program should execute cleanly. Class static methods seem to work as one would expect like in Python; just use the original function signature.
I'm using g++ 12.1.1, python 3.10.5 on Arch Linux. I hope this helps someone.

Calling C functions in Python

I have a bunch of functions that I've written in C and I'd like some code I've written in Python to be able to access those functions.
I've read several questions on here that deal with a similar problem (here and here for example) but I'm confused about which approach I need to take.
One question recommends ctypes and another recommends cython. I've read a bit of the documentation for both, and I'm completely unclear about which one will work better for me.
Basically I've written some python code to do some two dimensional FFTs and I'd like the C code to be able to see that result and then process it through the various C functions I've written. I don't know if it will be easier for me to call the Python from C or vice versa.
You should call C from Python by writing a ctypes wrapper. Cython is for making python-like code run faster, ctypes is for making C functions callable from python. What you need to do is the following:
Write the C functions you want to use. (You probably did this already)
Create a shared object (.so, for linux, os x, etc) or dynamically loaded library (.dll, for windows) for those functions. (Maybe you already did this, too)
Write the ctypes wrapper (It's easier than it sounds, I wrote a how-to for that)
Call a function from that wrapper in Python. (This is just as simple as calling any other python function)
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...
Well, here you are referring to two below things.
How to call c function within from python (Extending python)
How to call python function/script from C program (Embedding Python)
For #2 that is 'Embedding Python'
You may use below code segment:
#include "python.h"
int main(int argc, char *argv[]) {
Py_SetProgramName(argv[0]); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print 'Today is',ctime(time())\n");
/*Or if you want to run python file within from the C code*/
//pyRun_SimpleFile("Filename");
Py_Finalize();
return 0; }
For #1 that is 'Extending Python'
Then best bet would be to use Ctypes (btw portable across all variant of python).
>> from ctypes import *
>> libc = cdll.msvcrt
>> print libc.time(None)
>> 1438069008
>> printf = libc.printf
>> printf("Hello, %s\n", "World!")
>> Hello, World!
14
>> printf("%d bottles of beer\n", 42)
>> 42 bottles of beer
19
For detailed guide you may want to refer to my blog article:
It'll be easier to call C from python. Your scenario sounds weird - normally people write most of the code in python except for the processor-intensive portion, which is written in C. Is the two-dimensional FFT the computationally-intensive part of your code?
There's a nice and brief tutorial on this from Digital Ocean here. Short version:
1. Write C Code
You've already done this, so super short example:
#include <stdio.h>
int addFive(int i) {
return i + 5;
}
2. Create Shared Library File
Assuming the above C file is saved as c_functions.c, then to generate the .so file to call from python type in your terminal:
cc -fPIC -shared -o c_functions.so c_functions.c
3. Use Your C Code in Python!
Within your python module:
# Access your C code
from ctypes import *
so_file = "./c_functions.so"
c_functions = CDLL(so_file)
# Use your C code
c_functions.addFive(10)
That last line will output 15. You're done!
The answer from BLimitless quoting Digital Ocean is fine for simple cases, but it defaults to allowing int type arguments only. If need a different type for your input argument, for example to a float type, you need to add this:
c_functions.addFive.argtypes=[ctypes.c_float]
And if you change the output argument, for example to a float type you need this:
c_functions.addFive.restype=ctypes.c_float

Is it possible to call a C Function by reference from python??

I am a beginner in python and I need to test a C function which is being called by reference.
Here is my C File : myfile.c
#include<stdio.h>
int my_function(int *x)
{
int A;
printf("enter value of A");
scanf("%d",&A);
*x = 10 * A; // this sets the value to the address x is referencing to
return 0;
}
now,
my python script should call my_function() and pass the argument so that I can check and verify the result.
something like :
result = self.loaded_class.my_function(addressOf(some_variable))
self.assertEqual(some_variable,10)
Is this possible ?? how can i achieve this.
And I am writing scripts in python for auto tests , not using interactive python.
If you compile your file as a shared library or dll (I don't know how to do that), you can use ctypes like this (assuming it's a dll for this example):
import ctypes as ct
mylib = ct.cdll.myfile
c_int = ct.c_int(0)
mylib.my_function(ct.byref(c_int))
print c_int.value
You can write a Python interface for C function, a simple example is in Python doc. However, if all you want to do is test C function, you're probably better of with a C/C++ testing framework such as Google Test.

How to access a Python global variable from C?

I have some global variables in a Python script. Some functions in that script call into C - is it possible to set one of those variables while in C and if so, how?
I appreciate that this isn't a very nice design in the first place, but I need to make a small change to existing code, I don't want to embark on major refactoring of existing scripts.
I'm not a python guru, but I found this question interesting so I googled around. This was the first hit on "python embedding API" - does it help?
If the attributes belong to the global
scope of a module, then you can use
"PyImport_AddModule" to get a handle
to the module object. For example, if
you wanted to get the value of an
integer in the main module named
"foobar", you would do the following:
PyObject *m = PyImport_AddModule("__main__");
PyObject *v = PyObject_GetAttrString(m,"foobar");
int foobar = PyInt_AsLong(v);
Py_DECREF(v);
For anyone coming here from Google, here's the direct method:
PyObject* PyEval_GetGlobals()
https://docs.python.org/2/c-api/reflection.html
https://docs.python.org/3/c-api/reflection.html
The return value is accessed as a dictionary.
I recommend using pyrex to make an extension module you can store the values in in python, and cdef a bunch of functions which can be called from C to return the values there.
Otherwise, much depends on the type of values you're trying to transmit.
Are you willing to modify the API a little bit?
You can make the C function return the new value for the global, and then call it like this:
my_global = my_c_func(...)
If you're using Robin or the Python C API directly, you can pass the globals dictionary as an additional parameter and modify it
If your global is always in the same module, Sherm's solution looks great

Categories

Resources