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.
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.
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.
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:\Desktop\mytest> py -3.7 .\mytest.py
12
32
PS D:\Desktop\mytest> py -3.8 .\mytest.py
12
32
PS D:\Desktop\mytest> py -3.9 .\mytest.py
12
32
PS D:\Desktop\mytest> py -3.10 .\mytest.py
Traceback (most recent call last):
File "D:\Desktop\mytest\mytest.py", line 7, in <module>
lib = ctypes.CDLL('./libtest.dll', **mode)
File "D:\Python\3102\lib\ctypes\__init__.py", line 374, in __init__
self._handle = _dlopen(self._name, mode)
FileNotFoundError: Could not find module 'D:\Desktop\mytest\libtest.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:
My answer is based in the solutions provided here, here, and here
A common problem arises when the Python and compiler (g++) architectures does not match (i.e. 32 or 64 bit)
Related
I have a big c++ program in a single .cpp file which defines a lot of classes(interdependent of each other) and finally runs a main function. Now I am interested only in using one of this classes in python, specifically one method of this class which accepts 5 floats as inputs and outputs one float. I am trying to find the simplest method to achieve this. After not having success with boost:python(mainly because of installation issues) I have come to Cython which in the current version supports C++. I could successfully run the Rectangle example given in the Cython tutorial but I can't get how to proceed and adapt this to my case where I don't need a so complicated .pyx file, and where I don't have a .h file. Can somebody explain me in simple words what should I write in setup.py and in the .pyx file if my .cpp file has for example the structure:
...
class Nuclei {
public:
...
double potential(float,float,float,float,float);
...
private:
...
};
...
If all you are looking to do is call a single function, Extending Python With C/C++ is probably the simplest approach. This page provides a good example.
The relevant setup.py code in that example is
from distutils.core import setup, Extension
module1 = Extension('demo',
define_macros = [('MAJOR_VERSION', '1'),
('MINOR_VERSION', '0')],
include_dirs = ['/usr/local/include'],
libraries = ['tcl83'],
library_dirs = ['/usr/local/lib'],
sources = ['demo.c'])
setup (name = 'PackageName',
version = '1.0',
description = 'This is a demo package',
author = 'Martin v. Loewis',
author_email = 'martin#v.loewis.de',
url = 'http://docs.python.org/extending/building',
long_description = '''
This is really just a demo package.
''',
ext_modules = [module1])
If the C++ code you want to call is in demo.c, it could be used with import demo in Python.
Note that it is not nearly that simple- you'll be creating a function that takes a PyObject * with arguments and returns a PyObject *, and a lot can be said about how those are constructed. Take a look at the pages linked to above- they are filled with examples.
My app have some events, each event can have some actions. These actions is implemented in C++. I want to expose those core functions to python and use python to write the action. The advantage is I can modify actions without recompile. For example:
CppClass o;
// --- this is a action----
o.f1();
o.f2();
// ------------------------
use python to script the action:
def action1(o):
o.f1()
o.f2()
In c++, use interpreter to run this script, find action1 and call it with a PyObject which convert from c++ object. Actually, I have not expose f1() & f2() to python, I just use python to regroup the definition of action, all function is running by c++ binary code. Notice that I have not to give a definition of f1() & f2() in python.
The problem is: how I expose global functions? such as:
def action2():
gf1()
gf2()
boost::python can expose function, but it is different, it need compile a DLL file and the main() is belong to python script. Of course I can make global functions to be a class static member, but I just want to know. Notice that I HAVE TO give a definition of gf1() & gf2() in python.
Jython can do this easily: just import Xxx in python code and call Xxx.gf1() is ok. But in cython, how I define gf1() in python? This is a kind of extension, but extension requires Xxx be compiled ahead. It seems only way is make gf() into a class?
Solved. boost::python's doc is really poor...
For example: expose function
void ff(int x, int y)
{
std::cout<<x<<" "<<y<<std::endl;
}
to python:
import hello
def foo(x, y)
hello.ff(x, y)
you need to expose it as a module:
BOOST_PYTHON_MODULE(hello)
{
boost::python::def("ff", ff, boost::python::arg("x"), boost::python::arg("y"));
}
But this still is not a 'global function', so expose it to python's main scope:
BOOST_PYTHON_MODULE(__main__)
{
boost::python::def("ff", ff, boost::python::arg("x"), boost::python::arg("y"));
}
then you can write:
def foo(x, y)
ff(x, y)
You might also want to have a look at Cython.
Cython's main function is to translate (a subset of) Python code to C
or C++ code to build native code Python extensions. As a consequence,
it allows interfacing C/C++ code with a very terse and Python-ish
syntax.
Cython's user guide provides a
good example of how to call a simple C++ class from Python:
http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#declaring-a-c-class-interface
In addition to creating extensions, Cython can also generate C/C++
code that embeds the Python interpreter, so you do not need to build
and ship an external DLL. See details at: http://wiki.cython.org/EmbeddingCython
ffpython is c++ lib that wrap python 2.x api. see code repo
call python function: ffpython.call("fftest", "test_stl", a1, a2, a3);
reg c++ class:
ffpython.reg_class<foo_t, PYCTOR(int)>("foo_t")
.reg(&foo_t::get_value, "get_value")
.reg(&foo_t::set_value, "set_value")
.reg(&foo_t::test_stl, "test_stl")
.reg_property(&foo_t::m_value, "m_value");
I thought to try using D for some system administration scripts which require high performance (for comparing performance with python/perl etc).
I can't find an example in the tutorials I looked through so far (dsource.org etc.) on how to make a system call (i.e. calling another software) and receiving it's output from stdout, though?
If I missed it, could someone point me to the right docs/tutorial, or provide with the answer right away?
Well, then I of course found it: http://www.digitalmars.com/d/2.0/phobos/std_process.html#shell (Version using the Tango library here: http://www.dsource.org/projects/tango/wiki/TutExec).
The former version is the one that works with D 2.0 (thereby the current dmd compiler that comes with ubuntu).
I got this tiny example to work now, compiled with dmd:
import std.stdio;
import std.process;
void main() {
string output = shell("ls -l");
write(output);
}
std.process has been updated since... the new function is spawnShell
import std.stdio;
import std.process;
void main(){
auto pid = spawnShell("ls -l");
write(pid);
}
I have c++ code that has grown exponential. I have a number of variables (mostly Boolean) that need to be changed for each time I run my code (different running conditions). I have done this using the argument command line inputs for the main( int argc, char* argv[]) function in the past.
Since this method has become cumbersome (I have 18 different running conditions, hence 18 different argument :-( ), I would like to move to interfacing with python (if need be Bash ). Ideally I would like to code a python script, where I set the values of data members and then run the code.
Does anyone have a any pointer/information that could help me out? Better still a simple coded example or URL I could look up.
Edit From Original Question:
Sorry I don't think I was clear with my question. I don't want to use the main( int argc, char* argv[]) feature in c++. Instead of setting the variables on the command line. Can I use python to declare and initialize the data members in my c++ code?
Thanks again mike
Use subprocess to execute your program from python.
import subprocess as sp
import shlex
def run(cmdline):
process = sp.Popen(shlex.split(cmdline), stdout=sp.PIPE, stderr=sp.PIPE)
output, err = process.communicate()
retcode = process.poll()
return retcode, output, err
run('./a.out '+arg1+' '+arg2+' '+...)
Interfacing between C/C++ and Python is heavily documented and there are several different approaches. However, if you're just setting values then it may be overkill to use Python, which is more geared toward customising large operations within your process by farming it off to the interpreter.
I would personally recommend researching an "ini" file method, either traditionally or by using XML, or even a lighter scripting language like Lua.
You can use subprocess module to launch an executable with defined command-line arguments:
import subprocess
option1 = True
option2 = Frue
# ...
optionN = True
lstopt = ['path_to_cpp_executable',
option1,
option2,
...
optionN
]
lstopt = [str(item) for item in lstopt] # because we need to pass strings
proc = subprocess.Popen(lstrun, close_fds = True)
stdoutdata, stderrdata = proc.communicate()
If you're using Python 2.7 or Python 3.2, then OrderedDict will make the code more readable:
from collections import OrderedDict
opts = OrderedDict([('option1', True),
('option2', False),
]
lstopt = (['path_to_cpp_executable'] +
list(str(item) for item in opts.values())
)
proc = subprocess.Popen(lstrun, close_fds = True)
stdoutdata, stderrdata = proc.communicate()
With the ctypes module, you can call arbitrary C libraries.
There are several ways for interfacing C and C++ code with Python:
SWIG
Boost.Python
Cython
I can only advise to have a look at swig : using director feature, it allows to fully integrate C++ and python, including cross derivation from onle language to the other
I'm looking for a simple example code for C++\IronPython integration, i.e. embedding python code inside a C++, or better yet, Visual C++ program.
The example code should include: how to share objects between the languages, how to call functions\methods back and forth etc...
Also, an explicit setup procedure would help too. (How to include the Python runtime dll in Visual Studio etc...)
I've found a nice example for C#\IronPython here, but couldn't find C++\IronPython example code.
UPDATE - I've written a more generic example (plus a link to a zip file containing the entire VS2008 project) as entry on my blog here.
Sorry, I am so late to the game, but here is how I have integrated IronPython into a C++/cli app in Visual Studio 2008 - .net 3.5. (actually mixed mode app with C/C++)
I write add-ons for a map making applicaiton written in Assembly. The API is exposed so that C/C++ add-ons can be written. I mix C/C++ with C++/cli. Some of the elements from this example are from the API (such as XPCALL and CmdEnd() - please just ignore them)
///////////////////////////////////////////////////////////////////////
void XPCALL PythonCmd2(int Result, int Result1, int Result2)
{
if(Result==X_OK)
{
try
{
String^ filename = gcnew String(txtFileName);
String^ path = Assembly::GetExecutingAssembly()->Location;
ScriptEngine^ engine = Python::CreateEngine();
ScriptScope^ scope = engine->CreateScope();
ScriptSource^ source = engine->CreateScriptSourceFromFile(String::Concat(Path::GetDirectoryName(path), "\\scripts\\", filename + ".py"));
scope->SetVariable("DrawingList", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingList::typeid));
scope->SetVariable("DrawingElement", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingElement::typeid));
scope->SetVariable("DrawingPath", DynamicHelpers::GetPythonTypeFromType(AddIn::DrawingPath::typeid));
scope->SetVariable("Node", DynamicHelpers::GetPythonTypeFromType(AddIn::Node::typeid));
source->Execute(scope);
}
catch(Exception ^e)
{
Console::WriteLine(e->ToString());
CmdEnd();
}
}
else
{
CmdEnd();
}
}
///////////////////////////////////////////////////////////////////////////////
As you can see, I expose to IronPython some objects (DrawingList, DrawingElement, DrawingPath & Node). These objects are C++/cli objects that I created to expose "things" to IronPython.
When the C++/cli source->Execute(scope) line is called, the only python line
to run is the DrawingList.RequestData.
RequestData takes a delegate and a data type.
When the C++/cli code is done, it calls the delegate pointing to the
function "diamond"
In the function diamond it retrieves the requested data with the call to
DrawingList.RequestedValue() The call to DrawingList.AddElement(dp) adds the
new element to the Applications visual Database.
And lastly the call to DrawingList.EndCommand() tells the FastCAD engine to
clean up and end the running of the plugin.
import clr
def diamond(Result1, Result2, Result3):
if(Result1 == 0):
dp = DrawingPath()
dp.drawingStuff.EntityColor = 2
dp.drawingStuff.SecondEntityColor = 2
n = DrawingList.RequestedValue()
dp.Nodes.Add(Node(n.X-50,n.Y+25))
dp.Nodes.Add(Node(n.X-25,n.Y+50))
dp.Nodes.Add(Node(n.X+25,n.Y+50))
dp.Nodes.Add(Node(n.X+50,n.Y+25))
dp.Nodes.Add(Node(n.X,n.Y-40))
DrawingList.AddElement(dp)
DrawingList.EndCommand()
DrawingList.RequestData(diamond, DrawingList.RequestType.PointType)
I hope this is what you were looking for.
If you don't need .NET functionality, you could rely on embedding Python instead of IronPython. See Python's documentation on Embedding Python in Another Application for more info and an example. If you don't mind being dependent on BOOST, you could try out its Python integration library.