How can I use C++ class in Python?
Question:
I have implemented a class in C++. I want to use it with Python.
Please suggest step by step method and elaborate each step.
Somthing like this…
class Test{
private:
int n;
public:
Test(int k){
n=k;
}
void setInt(int k){
n = k;
}
int getInt(){
return n;
}
};
Now, in Python
>>> T1 = Test(12)
>>> T1.getInt()
12
>>> T1.setInt(32)
>>> T1.getInt()
32
Please suggest.How can I do this ?
NOTE: I would like to know manual way to do that. I don’t want any third party library dependency.
Answers:
I would suggest you try SWIG or sip (KDE/PyQt).
SWIG link : http://www.swig.org/
SIP link: http://freshmeat.net/projects/python-sip/
These can be used to wrap C++ classes and provide a Pythonic interface to them.
Look into Boost.Python. It’s a library to write python modules with C++.
Also look into SWIG which can also handle modules for other scripting languages. I’ve used it in the past to write modules for my class and use them within python. Works great.
You can do it manually by using the Python/C API, writing the interface yourself. It’s pretty lowlevel, but you will gain a lot of additional knowledge of how Python works behind the scene (And you will need it when you use SWIG anyway).
ctypes is good. It is really easy to use, and it comes standard with Python. Unfortunately it can only talk to shared libraries (Unix) or DLLs (Windows) that have a C-style interface, which means you can’t directly interface to a C++ object. But you could use a handle system where a handle refers to a particular object.
>>> getInt(h)
12
I think that is simple, easy to understand, and doesn’t require extra libraries.
This is a very old post, and probably the OP already found a solution to his problem, but since no one has yet provided a valid example, I will give it a try and maybe help someone like me with the same problem in hand.
Since the OP did not specify, I will restrict my answer to Windows, although a Linux solution would be straightforward. I will try to provide a minimal working example that reproduces the code in question.
Step 1) Start with the C++ code (a single file)
class Test{
private:
int n;
public:
Test(int k){
n=k;
}
void setInt(int k){
n = k;
}
int getInt(){
return n;
}
};
extern "C"
{
// include below each method you want to make visible outside
__declspec(dllexport) Test* init(int k) {return new Test(k);}
__declspec(dllexport) void setInt(Test *self, int k) {self->setInt(k);}
__declspec(dllexport) int getInt(Test *self) {return self->getInt();}
// Note: the '__declspec(dllexport)' is only necessary in Windows
}
Step 2) Compile the DLL shared library. E.g. from your working directory:
g++ -shared mytest.cpp -o libtest.dll
Step 3) Create the Python file with the wrapper:
# mytest.py
import ctypes
import platform
# From Python 3.8 onwards, there is a reported bug in CDLL.__init__()
mode = dict(winmode=0) if platform.python_version() >= '3.8' else dict()
lib = ctypes.CDLL('./libtest.dll', **mode)
class Test(object):
def __init__(self, val: int):
# Declare input and output types for each method you intend to use
lib.init.argtypes = [ctypes.c_int]
lib.init.restype = ctypes.c_void_p
lib.setInt.argtypes = [ctypes.c_void_p, ctypes.c_int]
lib.setInt.restype = ctypes.c_void_p
lib.getInt.argtypes = [ctypes.c_void_p]
lib.getInt.restype = ctypes.c_int
self.obj = lib.init(val)
def setInt(self, n):
lib.setInt(self.obj, n)
def getInt(self):
return lib.getInt(self.obj)
T1 = Test(12)
print(T1.getInt())
T1.setInt(32)
print(T1.getInt())
Step 4) Run the code
Below are my results when I run the script with 4 different Python versions:
PS D:Desktopmytest> py -3.7 .mytest.py
12
32
PS D:Desktopmytest> py -3.8 .mytest.py
12
32
PS D:Desktopmytest> py -3.9 .mytest.py
12
32
PS D:Desktopmytest> py -3.10 .mytest.py
Traceback (most recent call last):
File "D:Desktopmytestmytest.py", line 7, in <module>
lib = ctypes.CDLL('./libtest.dll', **mode)
File "D:Python3102libctypes__init__.py", line 374, in __init__
self._handle = _dlopen(self._name, mode)
FileNotFoundError: Could not find module 'D:Desktopmytestlibtest.dll' (or one of its dependencies). Try using the full path with constructor syntax.
In the last case, I have tried with the full path and still same error.
I’m running on Windows 10 64bit and compiling with g++ 8.1.0 from MinGW64
Comments:
I have implemented a class in C++. I want to use it with Python.
Please suggest step by step method and elaborate each step.
Somthing like this…
class Test{
private:
int n;
public:
Test(int k){
n=k;
}
void setInt(int k){
n = k;
}
int getInt(){
return n;
}
};
Now, in Python
>>> T1 = Test(12)
>>> T1.getInt()
12
>>> T1.setInt(32)
>>> T1.getInt()
32
Please suggest.How can I do this ?
NOTE: I would like to know manual way to do that. I don’t want any third party library dependency.
I would suggest you try SWIG or sip (KDE/PyQt).
SWIG link : http://www.swig.org/
SIP link: http://freshmeat.net/projects/python-sip/
These can be used to wrap C++ classes and provide a Pythonic interface to them.
Look into Boost.Python. It’s a library to write python modules with C++.
Also look into SWIG which can also handle modules for other scripting languages. I’ve used it in the past to write modules for my class and use them within python. Works great.
You can do it manually by using the Python/C API, writing the interface yourself. It’s pretty lowlevel, but you will gain a lot of additional knowledge of how Python works behind the scene (And you will need it when you use SWIG anyway).
ctypes is good. It is really easy to use, and it comes standard with Python. Unfortunately it can only talk to shared libraries (Unix) or DLLs (Windows) that have a C-style interface, which means you can’t directly interface to a C++ object. But you could use a handle system where a handle refers to a particular object.
>>> getInt(h)
12
I think that is simple, easy to understand, and doesn’t require extra libraries.
This is a very old post, and probably the OP already found a solution to his problem, but since no one has yet provided a valid example, I will give it a try and maybe help someone like me with the same problem in hand.
Since the OP did not specify, I will restrict my answer to Windows, although a Linux solution would be straightforward. I will try to provide a minimal working example that reproduces the code in question.
Step 1) Start with the C++ code (a single file)
class Test{
private:
int n;
public:
Test(int k){
n=k;
}
void setInt(int k){
n = k;
}
int getInt(){
return n;
}
};
extern "C"
{
// include below each method you want to make visible outside
__declspec(dllexport) Test* init(int k) {return new Test(k);}
__declspec(dllexport) void setInt(Test *self, int k) {self->setInt(k);}
__declspec(dllexport) int getInt(Test *self) {return self->getInt();}
// Note: the '__declspec(dllexport)' is only necessary in Windows
}
Step 2) Compile the DLL shared library. E.g. from your working directory:
g++ -shared mytest.cpp -o libtest.dll
Step 3) Create the Python file with the wrapper:
# mytest.py
import ctypes
import platform
# From Python 3.8 onwards, there is a reported bug in CDLL.__init__()
mode = dict(winmode=0) if platform.python_version() >= '3.8' else dict()
lib = ctypes.CDLL('./libtest.dll', **mode)
class Test(object):
def __init__(self, val: int):
# Declare input and output types for each method you intend to use
lib.init.argtypes = [ctypes.c_int]
lib.init.restype = ctypes.c_void_p
lib.setInt.argtypes = [ctypes.c_void_p, ctypes.c_int]
lib.setInt.restype = ctypes.c_void_p
lib.getInt.argtypes = [ctypes.c_void_p]
lib.getInt.restype = ctypes.c_int
self.obj = lib.init(val)
def setInt(self, n):
lib.setInt(self.obj, n)
def getInt(self):
return lib.getInt(self.obj)
T1 = Test(12)
print(T1.getInt())
T1.setInt(32)
print(T1.getInt())
Step 4) Run the code
Below are my results when I run the script with 4 different Python versions:
PS D:Desktopmytest> py -3.7 .mytest.py
12
32
PS D:Desktopmytest> py -3.8 .mytest.py
12
32
PS D:Desktopmytest> py -3.9 .mytest.py
12
32
PS D:Desktopmytest> py -3.10 .mytest.py
Traceback (most recent call last):
File "D:Desktopmytestmytest.py", line 7, in <module>
lib = ctypes.CDLL('./libtest.dll', **mode)
File "D:Python3102libctypes__init__.py", line 374, in __init__
self._handle = _dlopen(self._name, mode)
FileNotFoundError: Could not find module 'D:Desktopmytestlibtest.dll' (or one of its dependencies). Try using the full path with constructor syntax.
In the last case, I have tried with the full path and still same error.
I’m running on Windows 10 64bit and compiling with g++ 8.1.0 from MinGW64
Comments: