Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use C++ classes with ctypes?

Tags:

c++

python

ctypes

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.

like image 330
jörg Avatar asked Oct 23 '09 20:10

jörg


People also ask

Can ctypes be used with C++?

ctypes is a foreign function library for Python that provides C compatible data types. Although it is mostly used to consume C and C++ libraries, you can use ctypes with libraries written in any language that can export a C compatible API, e.g. Fortran, Rust.

How do I use ctypes library?

Make sure ctypes can find the library by putting it in /usr/lib or another standard directory. If you do this, you don't need to specify the full path when writing the wrapper. If you choose not to do this, you must provide the full path of the library when calling ctypes. CDLL() .

Is ctypes part of Python?

ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries.

What is ctypes in Python?

ctypes — A foreign function library for Python¶. ctypes is a foreign function library for Python. It provides C compatible data types, and allows calling functions in DLLs or shared libraries. It can be used to wrap these libraries in pure Python.

Is it possible to access C++ classes through Python's ctypes?

Until then, you're probably not going to have any way to access C++ classes through Python's ctypes. Show activity on this post. The answer by AudaAero is very good but not complete (at least for me).

What is the difference between ctypes name and library?

Some types accept other objects as well. This method returns a ctypes type instance exported by a shared library. name is the name of the symbol that exports the data, library is the loaded shared library. Common instance variables of ctypes data types:

What are the common methods of ctypes data types?

Common methods of ctypes data types, these are all class methods (to be exact, they are methods of the metaclass): from_buffer (source offset]) ¶ This method returns a ctypes instance that shares the buffer of the source object. The source object must support the writeable buffer interface.


1 Answers

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

like image 50
AudaAero Avatar answered Sep 26 '22 08:09

AudaAero