Template export troubles - c++

I can't understand the right way for exporting some function into python with boost.python.
I have exported this class CL_Rectf. It inherits CL_Rectx<float>.
Now I want to export function bounding_rect:
# In CL_Rectf class exporting
.def("BoundingRect", &CL_Rectf::bounding_rect, PYPOLICY_REFERENCE_EXISTING)
It compiles, but when I use this code in python:
mBox = CL_Rectf()
mBox.BoundingRect(CL_Rectf(x, y, x2, y2))
I have such error:
Boost.Python.ArgumentError: Python argument types in
CL_Rectf.BoundingRect(CL_Rectf, CL_Rectf)
did not match C++ signature:
BoundingRect(CL_Rectf {lvalue}, CL_Rectx<float>)
Something wrong with exporting due to CL_Rectx in c++ signature. What's wrong?

Without knowing Boost.Python in particular, it seems to me that you exported CL_Rectf, but not CL_Rectx<float>. So when asked to convert a python object into a CL_Rectx<float>, Boost.Python doesn't know how, and raises the exception you see.
My advice would be be to forget about CL_Floatf and export the CL_Rectx<float> class instead. CL_Rectf as a C++ class is a bad idea on so many levels; you should try to avoid its use even in C++.

Related

How to call Python from C++?

From the docs :
cppyy is an automatic, run-time, Python-C++ bindings generator, for
calling C++ from Python and Python from C++.
(Emphasis mine)
I don't see any instructions for doing the same, however, so is it possible to call Python via C++ using cppyy?
As a qualifier, since I don't know from where you obtained cppyy, the main code that was at the time the reason for typing that sentence does not exist in cppyy master, but does exist in its historic home of PyROOT. This so-called "class generator" plugin allows Cling to "see" Python classes as C++ classes, for straightforward callbacks and even inheritance of C++ classes from Python ones. See this publication (page 3) for some examples: https://www.researchgate.net/publication/288021806_Python_in_the_Cling_World
This code was not ported over to cppyy standalone b/c the class generator relies on interactive use (specifically, dynamic scopes), so only works from Cling, not compiled code, and there is no way (yet) to drop into the Cling prompt from Python (vice versa works).
The reason why that sentence is still there even without the class generator, is that cppyy has since grown a multitude of other ways to call Python from C++ (these have been backported into PyROOT). Examples include C-style function pointers, C++ std::function<> objects, lambdas, and cross-language inheritance. Moreover, these can all be used by importing cppyy into embedded Python (and thus be used from compiled C++).
See e.g. these examples in the documentation: callbacks and cross-inheritance. Cross-inheritance is probably the easiest to use: just define an abstract interface, implement it in Python, pass the pointer to C++ and use it like you would with any pointer-to-interface in C++. For callbacks, declare an extern function pointer (or std::function object) in a header, pass that in a cppyy.include in embedded Python, assign a Python function to that pointer, then call it in C++ as desired.
Callbacks can be made quite sophisticated, assuming that the C++ side can handle it. For example, by providing annotations on the Python side, Python functions can instantiate C++ function pointer templates. Take the completely generic callback in C++ below, which accepts any arguments and producing any result:
>>> import cppyy
>>> cppyy.cppdef("""\
... template<typename R, typename... U, typename... A>
... R callT(R(*f)(U...), A&&... a) {
... return f(a...);
... }""")
True
>>> def f(a: 'int') -> 'double':
... return 3.1415*a
...
>>> cppyy.gbl.callT(f, 2)
6.283
>>> def f(a: 'int', b: 'int') -> 'int':
... return 3*a*b
...
>>> cppyy.gbl.callT(f, 6, 7)
126
>>>
The final way of calling from C++ into Python is indeed not documented b/c it is (still) only available for CPython/cppyy, not PyPy/_cppyy and the naming is implementation-specific as well: CPyCppyy/API.h.
This header is meant to be included in C++ code, allowing the boxing and unboxing of cppyy-bound instances from C++, custom converters and executors, memory management, and parameter packing for stub functions. There are also a couple of convenience functions for dealing with one-offs. For example:
import cppyy
def pyfunc():
return 42
cppyy.cppdef("""\
#include "CPyCppyy/API.h"
int cppfunc() {
return (int)CPyCppyy::Eval("pyfunc()");
}""")
print(cppyy.gbl.cppfunc())
(although the example here is run from Python for convenience, this can all be called from embedded Python in compiled C++ as well).
I do not know if it answer to your question (from your title I understand that you want to call python function from c++ side, but later it seems you ask specifically about cpppy) but you can do the binding with pybind11. This package is heavily used and is being used in a lot of case as an alternative to swig (to understand the differences have a look at this open thread in the TensorFlow community). These are the two most used packages for Python-C++ binding.
To see how to call a python function in C++ for Pybind11 have a look at this question, while to see how to call a python function in C++ for swig have a look at this question.

string arguments are not recognized by SWIG

I have a frustrating problem which got me spend a lot of time dealing with it but I did not find any solution.
I want to use C++ class in PHP with SWIG. I generated my shared object and it works fine for some methods but I've got this error whenever I call the methods with string arguments as their input:
Fatal error: Type error in argument 2 of PKI_Buf_initHex. Expected SWIGTYPE_p_std__string
PKI_Buf_initHex is the name of the wrapper class which SWIG made automatically. In my C++ code I declare initHex method as:
int initHex(const string x)
{..}
I included typemaps.i and std_string.i in my interface file but I got the same error message.
I truly would appreciate if anyone can help me with this issue.
You need to have:
%include <std_string.i>
Early enough in the SWIG interface (i.e. before std::string is first seen).

How do I call a function defined in C++ object from a python program?

I have a C++ program:
class X
{
private:
int a;
public:
int func(char *str);
};
Now I want to call the function func in my Python program. How can I do it?
I have successfully called C functions from my Python program using ctypes.
However I can't seem to figure out how to call functions defined inside C++ objects.
I have already worked with ctypes, so I would like to figure out how to accomplishing it that way. However I'm open to other techniques. Also my project puts a constarint that I am not supposed to use wrapper function in my C++ program.
Check out Boost::Python.
You tagged the question ctypes, but you cannot instantiate a C++ object directly from ctypes. You can wrap the C++ object in a C interface and then use ctypes. Or you could write a Python extension module which could include C++ code.
An alternative to Boost.Python is SWIG.
try http://swig.org/
years ago i wrapped some c/c++ code to use them in wxPython with swig.
i cannot remember too much details but i think swig is easy to use.
Hope that helps.

How do I wrap a C++ class with Cython?

I have a C++ class. It's made up of one .ccp file and one .h file. It compiles (I can write a main method that uses it successfully in c++). How do I wrap this class with Cython to make it available in Python?
I've read the docs and don't follow. They talk about generating the cpp file. When I've tried to follow the docs, my already existing cpp gets blown away...
What am I meant to put in the pyx file? I've been told the class definition but how much of it? Just the public methods?
Do I need a .pxd file? I don't understand when this file is or isn't required.
I've tried asking these question in the #python IRC channel and can't get an answer.
Even Cython is generally for use with C, it can generate C++ code, too. When compiling, you add the --cplus flag.
Now, creating a wrapper for the class is simple and not much different from wrapping a structure. It mainly differs from declaring the extern, but that's not much difference at all.
Suppose you have a class MyCppClass in mycppclass.h.
cdef extern from "mycppclass.h":
cppclass MyCppClass:
int some_var
MyCppClass(int, char*)
void doStuff(void*)
char* getStuff(int)
cdef class MyClass:
# the public-modifier will make the attribute public for cython,
# not for python. Maybe you need to access the internal C++ object from
# outside of the class. If not, you better declare it as private by just
# leaving out the `private` modifier.
# ---- EDIT ------
# Sorry, this statement is wrong. The `private` modifier would make it available to Python,
# so the following line would cause an error es the Pointer to MyCppClass
# couldn't be converted to a Python object.
#>> cdef public MyCppClass* cobj
# correct is:
cdef MyCppClass* obj
def __init__(self, int some_var, char* some_string):
self.cobj = new MyCppClass(some_var, some_string)
if self.cobj == NULL:
raise MemoryError('Not enough memory.')
def __del__(self):
del self.cobj
property some_var:
def __get__(self):
return self.cobj.some_var
def __set__(self, int var):
self.cobj.some_var = var
Note that the new keyword is only available when the --cplus flag is set, otherwise use malloc from <stdlib.h> by externing it.
Also note that you don't need to dereference the pointer (->) to call the method. Cython tracks the object's type and applies what fits.
.pxd files are for seperating declarations from implementation, or to avoid namespace colliding. Imagine you'd like to name you Python-wrapper like the C++ class. Simply put in your .pxd file the extern declarations and cimport the pxd file in the .pyx.
cimport my_pxd
cdef my_pxd.SomeExternedType obj
Note that you can not write implementations in a .pxd file.
So after lots of poking, trial and error, screaming and tearing my hair out, I finally got this to work. First though, I had to re-write my C++ into C, which for me really just involved converting all my std::string variables to char* and keeping track of some lengths.
Once done I had my .h and .c files. I wanted to make a single function from the C code available in Python. It turns out that Cython can compile your C files into the extension for you and link any libraries all in one go, so starting with my setup.py, it ended up looking like this:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
ext_modules=[
Extension("myext",
["myext.pyx", "../stuff.c"],
libraries=["ssl", "crypto"]
)
]
setup(
name = "myext",
cmdclass = {"build_ext": build_ext},
ext_modules = ext_modules
)
As you can see, the second argument to the Extension simply lists all the files that need to be compiled, Cython works out how to compile them depending on their file extension as far as I can tell. The libraries array tells the Cython compiler what needs to be linked in (in this case I was wrapping some crypto stuff that I couldn't seem to mimick directly through existing Python libs).
To actually make my C function available in the .pyx file, you write a small wrapper in the .pxd. My myext.pxd looked as below:
cdef extern from "../stuff.h":
char* myfunc(char* arg1, char* arg2, char* arg3)
In the .pyx you then use the cimport declaration to import this function, which is then available for use as if it were any other Python function:
cimport myext
def my_python_func(arg1, arg2, arg3):
result = myext.myfunc(arg1, arg2, arg3)
return result
When you build this (on Mac at least) you get a .so that you can import in python and run the functions from the .pyx. There may be better, more correct way to get this all working but that comes from experience and this was a first encounter that I managed to work out. I'd be very interested on pointers where I may have gone wrong.
Update:
After further use of Cython, I found it was super simple to integrate it with C++ too, once you know what you're doing. Making C++'s string available is as simple as from libcpp.string cimport string in your pyx/pyd. Declaring the C++ class is similarly easy as:
cdef extern from "MyCPPClass.h":
cdef cppclass MyCPPClass:
int foo;
string bar;
Sure you have to basically redeclare the .h definition of your class in a Pythonic format, but that's a small price to pay for getting access to your already written C++ functions.
Cython is mainly for C development, to integrate C++ with Python I would recommend Boost.Python. Their excellent documentation should get you started pretty quickly.
The answers above have more or less answered the OP's question.
But its now passing the mid of 2020 and I'd thought to put a contribution (in the form of resource summary) here for those who want to explore Python-C++ bindings via python packages that can be 'pip installed' (or in the PyPI).
I'd reckon for calling C++ from Python / wrapping over third party libs , one can look at cppyy. Its a relatively young project but it certainly looks promising and backed with a modern compiler. See the link below:
https://cppyy.readthedocs.io/en/latest/
Also, there's always pybind11 ....
https://github.com/pybind/pybind11
Cython also supports C++ natively (for most of the C++ languages) ; for more information see https://cython.readthedocs.io/en/latest/src/userguide/wrapping_CPlusPlus.html

How to call a JNI DLL from C++

I have a task to interface with a dll from a third party company using C++.
The dll package comes with:
the dll itself
a sample Java implementation - consists of a java wrapper(library) generated using the SWIG tool and the the java source file
documentation that states all the public datatypes, enumeration and member functions.
My other colleague is using Java(based on the example in package) to interface with the dll while I'm asked to use C++. The Java example looks straight forward... just import the wrapper and instantiate any class described in the docs..
More info on the dll:
From the docs, it says the dll was programmed using C++
From a hexdump, it shows that it was compiled using VC90 (VS C++ 2008 right?) and something from Dinkumware.
From a depends.exe output, the functions seems to be wrapped under JNI. For example: _Java_mas_com_oa_rollings_as_apiJNI_Server_1disconnect#20
My dilemma:
The dll company is not changing anything in the dll and not providing any other info.
How do i use the member functions in the class from the dll?
I did some simple LoadLibrary() and GetProcAddress and manage to get the address of the public member functions.
But i dunno how to use the functions that has the datatype parameters defined in the dll. For example:
From the docs, the member function is defined as:
void Server::connect(const StringArray, const KeyValueMap) throw(std::invalid_argument,std::out_of_range)
typedef std::map Server::KeyValueMap
typedef std::vector Server::StringArray
how do i call that function in C++. The std::map and std::vector in my compiler (VS 2005) has different functions listing that the one in the dll. For example, from the depends.exe output:
std::map // KeyValueMap - del, empty, get, has_1key,set
std::vector // StringArray - add, capacity, clear, get, isEMPTY, reserve, set, size
Any advice/strategy on how i should solve this? Is it possible to simply instantiate the class like the Java example?
If you are trying to use VS 2005 to try and interface with a DLL that is built using VS2008, your attempts will be mostly doomed unless you can use a plain C interface. Given your description, this is not the case; The runtime libraries differ between VS2005 and VS2008 so there is little chance that the object layout has stayed the same between compilers. The 'something from Dinkumware' that you're referring to is most likely the C++ standard library as ISTR that Microsoft uses the Dinkumware one.
With your above example you're also missing several important pieces of information - the types you describe (Server::StringArray and Server::KeyValueMap) are standard library containers. OK fine, but standard library containers of what? These containers are templates and unless you know the exact types these templates have been instantiated with, you're a little stuck.
Is this DLL intended to be called from C++ at all? The fact that it export a JNI interface suggests that it might not be in the first place. Does it export any other public symbols apart from those that are of the format _Java_...?
Of course if there is no other way in and you must use C++ instead of Java, you might want to look into embedding a JVM into your C++ app and use that to call through to the C++ dll. It's not what I'd call an elegant solution but it might well work.
I don't quite understand the use of C++ standard library data types here. How can Java code provide a std::map argument? Are the arguments you pass in always just "opaque" values you would get as output from a previous call to the library? That's the only way you're going to be able to make it work from code under a different runtime.
Anyway...
When you make a JNI module, you run javah.exe and it generates a header file with declarations like:
JNIEXPORT void JNICALL Java_Native_HelloWorld(JNIEnv *, jobject);
Do you have any such header file for the module?
These symbols are exported as extern "C" if I recall correctly, so if you can get the correct signatures, you should have no issues with name mangling or incompatible memory allocators, etc..
The "#20" at the end of the method signature means that the function is declared "stdcall" and that 20 bytes are put on the stack when the function is called. All these methods should start with a JNIEnv* and a jobject, these will total 8 bytes I believe, on a 32-bit environment, so that leaves 12 bytes of parameters you will need to know in order to generate a correct function prototype.
Once you figure out what the parameters are, you can generate something like this:
typedef void (__stdcall *X)(JNIEnv *, jobject, jint i, jboolean b);
Then, you can cast the result of GetProcAddress to an X and call it from your C++ code.
X x = (X)GetProcAddress(module, "name");
if (x) x(params...);
Unfortunately, what you have doesn't quite look like what I have seen in the past. I am used to having to deal with Java data types from C/C++ code, but it looks like this module is dealing with C++ data types in Java code, so I don't know how relevant any of my experience is. Hopefully this is some help, at least.