How can I call a c++ function using python - python

I want to know if there's a way to use a c++ function inside a python code
For example, after doing my research I did find this solution using .dll file.
But It can't find the function
My code:
fun.cpp:
#include <iostream>
extern int add(int a, int b) {
return a+b;
}
int main()
{
std::cout << "Hello World! from C++" << std::endl;
return 0;
}
compiling it using cmd:
g++ fun.cpp -o fun.dll
Calling the function using Python, ctypes:
from ctypes import *
import os
mydll = cdll.LoadLibrary("C:/Users/User/Desktop/ctypes/fun.dll")
result= mydll.add(10,1)
print("Addition value:-"+result)
But I had this error:
Traceback (most recent call last): File
"c:\Users\User.vscode\extensions\ms-python.python-2019.10.41019\pythonFiles\ptvsd_launcher.py",
line 43, in
main(ptvsdArgs) File "c:\Users\User.vscode\extensions\ms-python.python-2019.10.41019\pythonFiles\lib\python\old_ptvsd\ptvsd__main__.py",
line 432, in main
run() File "c:\Users\User.vscode\extensions\ms-python.python-2019.10.41019\pythonFiles\lib\python\old_ptvsd\ptvsd__main__.py",
line 316, in run_file
runpy.run_path(target, run_name='main') File "C:\Python36\lib\runpy.py", line 263, in run_path
pkg_name=pkg_name, script_name=fname) File "C:\Python36\lib\runpy.py", line 96, in _run_module_code
mod_name, mod_spec, pkg_name, script_name) File "C:\Python36\lib\runpy.py", line 85, in _run_code
exec(code, run_globals) File "c:\Users\User\Desktop\ctypes\test.py", line 5, in
result= mydll.add(10,1) File "C:\Python36\lib\ctypes__init__.py", line 361, in getattr
func = self.getitem(name) File "C:\Python36\lib\ctypes__init__.py", line 366, in getitem
func = self._FuncPtr((name_or_ordinal, self)) AttributeError: function 'add' not found

C++ mangles exported names. Here's an example that should compile on Windows and Linux. __declspec(dllexport) is required to export a function on Windows, but not Linux. extern "C" is required to export the function name using C conventions, instead of the name-mangled C++ conventions. The name-mangling is required in C++ to indicate the function parameters and return type, since C++ can have multiple functions with the same name but take different parameters. The C convention does not support multiple functions with the same name.
fun.cpp:
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
extern "C" API int add(int a, int b) {
return a+b;
}
Python:
from ctypes import *
dll = CDLL('fun')
result = dll.add(10,1)
print('Addition value:',result)
Output:
Addition value: 11

I think you should check Python's LoadLibrary is calling "fun.dll"'s main() function correctly. It should look for the DllMain() function when loading, then you need to get the function address to call the function.

Related

NameError: name 'ResourceWarning' is not defined

java version "1.8.0_311"
Python 3.10.8
Sikuli:-
<dependency>
<groupId>sikulixapi</groupId>
<artifactId>sikulixapi</artifactId>
<scope>system</scope>
<version>2.0.5</version>
<systemPath>${project.basedir}/sikulixapi-2.0.5.jar</systemPath>
</dependency>
I am getting the below error while running a sample python program from java.
Exception in thread "main" Traceback (most recent call last):
File "foo\boo\sikulixapi-2.0.5.jar\Lib\site.py", line 68, in <module>
File "foo\boo\sikulixapi-2.0.5.jar\Lib\os.py", line 64, in <module>
File "foo\boo\sikulixapi-2.0.5.jar\Lib\ntpath.py", line 12, in <module>
File "foo\boo\sikulixapi-2.0.5.jar\Lib\warnings.py", line 395, in <module>
File "foo\boo\sikulixapi-2.0.5.jar\Lib\warnings.py", line 395, in <module>
File "__pyclasspath__/_warnings.py", line 105, in <module>
NameError: name 'ResourceWarning' is not defined
Python:-
class Hello:
__gui = None
def __init__(self, gui):
self.__gui = gui
def run(self):
print('Hello world!')
Java
package Types.UserInterface.Utilities;
import org.python.core.PyInstance;
import org.python.util.PythonInterpreter;
public class InterpreterExample {
PythonInterpreter interpreter = null;
public InterpreterExample() {
PythonInterpreter.initialize(System.getProperties(),
System.getProperties(), new String[0]);
this.interpreter = new PythonInterpreter();
}
void execfile(final String fileName) {
this.interpreter.execfile(fileName);
}
PyInstance createClass(final String className, final String opts) {
return (PyInstance) this.interpreter.eval(className + "(" + opts + ")");
}
public static void main(String gargs[]) {
InterpreterExample ie = new InterpreterExample();
ie.execfile("hello.py");
PyInstance hello = ie.createClass("Hello", "None");
hello.invoke("run");
}
}
Not sure why it is conflicting with sikuli classes while running the sample java program.
Note: Python program works perfectly fine when they are executed directly. Problem raises only when the same program is called in java.
Could someone give a direction as to what is the approach to fix this?
cf Learning how to use Jython - ResourceWarning error
Jython currently only works with Python 2, you can't use Python 3 with it (for now), hence the error.

When I use py++ to generate then boost.Python wrapper on macOS, I got a error about std::string?

The code I want to generate wrapper for is
#include <string>
#include <iostream>
class Dog
{
public:
Dog(int age, std::string name):age_(age),name_(name){}
void bark()
{
std::cout<<"Wang! Wang!"<<std::endl;
}
private:
int age_;
std::string name_;
};
And the generate python code is as follow:
from pygccxml import parser
from pyplusplus import module_builder
generator_path="/usr/local/bin/castxml"
generator_name="castxml"
compiler="clang++"
compiler_path="/usr/bin/clang++"
xml_generator_config=parser.xml_generator_configuration_t(xml_generator_path=generator_path,
xml_generator=generator_name,
compiler=compiler,
compiler_path=compiler_path)
header_collection=["Bonjour.hpp"]
builder=module_builder.module_builder_t(header_collection,xml_generator_path=generator_path,
xml_generator_config=xml_generator_config)
builder.classes().add_properties(exclude_accessors=True)
builder.build_code_creator(module_name="pylib_auto")
builder.write_module('pylib_auto.cpp')
I run with the command:
python3 pylib_generator.py
And I got the follow error:
INFO Parsing source file "Bonjour.hpp" ...
In file included from Bonjour.hpp:1:
In file included from /Library/Developer/CommandLineTools/usr/include/c++/v1/string:469:
/Library/Developer/CommandLineTools/usr/include/c++/v1/__config:235:11: fatal error: 'endian.h' file not found
# include <endian.h>
^~~~~~~~~~
1 error generated.
Traceback (most recent call last):
File "pylib_generator.py", line 17, in <module>
xml_generator_config=xml_generator_config)
File "/usr/local/lib/python3.6/site-packages/pyplusplus/module_builder/boost_python_builder.py", line 106, in __init__
, indexing_suite_version)
File "/usr/local/lib/python3.6/site-packages/pyplusplus/module_builder/boost_python_builder.py", line 149, in __parse_declarations
decls = reader.read_files( files, compilation_mode )
File "/usr/local/lib/python3.6/site-packages/pygccxml/parser/project_reader.py", line 264, in read_files
return self.__parse_file_by_file(files)
File "/usr/local/lib/python3.6/site-packages/pygccxml/parser/project_reader.py", line 292, in __parse_file_by_file
decls = reader.read_file(header)
File "/usr/local/lib/python3.6/site-packages/pygccxml/parser/source_reader.py", line 356, in read_file
return self.read_cpp_source_file(source_file)
File "/usr/local/lib/python3.6/site-packages/pygccxml/parser/source_reader.py", line 375, in read_cpp_source_file
xml_file = self.create_xml_file(ffname)
File "/usr/local/lib/python3.6/site-packages/pygccxml/parser/source_reader.py", line 324, in create_xml_file
": %s status:%s" % (gccxml_msg, exit_status))
RuntimeError: Error occurred while running CASTXML: status:1
Then I tried to do a soft link of endian.h
ln -s /usr/include/machine/endian.h /usr/local/include/endian.h
And I got the follow error:
INFO Parsing source file "Bonjour.hpp" ...
In file included from Bonjour.hpp:1:
In file included from /Library/Developer/CommandLineTools/usr/include/c++/v1/string:469:
In file included from /Library/Developer/CommandLineTools/usr/include/c++/v1/__config:235:
/usr/local/include/endian.h:37:2: error: architecture not supported
#error architecture not supported
^
In file included from Bonjour.hpp:1:
In file included from /Library/Developer/CommandLineTools/usr/include/c++/v1/string:469:
/Library/Developer/CommandLineTools/usr/include/c++/v1/__config:906:1: error: '__declspec' attributes are not enabled; use '-fdeclspec' or
'-fms-extensions' to enable support for __declspec attributes
_LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/__config:583:37: note: expanded from macro '_LIBCPP_FUNC_VIS'
#define _LIBCPP_FUNC_VIS _LIBCPP_DLL_VIS
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/__config:576:26: note: expanded from macro '_LIBCPP_DLL_VIS'
# define _LIBCPP_DLL_VIS __declspec(dllimport)
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/__config:940:4: error: "No thread API"
PS:
ProductName: Mac OS X
ProductVersion: 10.13.3
BuildVersion: 17D47
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin17.4.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
I want to know why it got these error,seemly I can compile with clang++ .thanks anyone who can answer this!!!
I manual compile castxml on my mac, and there is no question any more. and before I just install castxml with brew. hope to be useful!
I'm not sure what makes you conclude there is a problem with std::string.
I can see a few interesting things, though:
/Library/Developer/CommandLineTools/usr/include/c++/v1/__config:940:4: error: "No thread API"
This probably indicates you need to link thread support. Compilers commonly use the -pthread flag, but you may need to also specify a linker input (instead?) on your platform. On gcc/clang it would usually be -pthread and -lpthread for the linker input
/Library/Developer/CommandLineTools/usr/include/c++/v1/__config:906:1: error: '__declspec' attributes are not enabled; use '-fdeclspec' or
'-fms-extensions' to enable support for __declspec attributes
Try using -fms-extensions or -fdeclspec

Parsing struct within struct in C using pycparser?

I have this example c file I want to parse:
StrcutWithinStruct.c
// simple struct within a struct example
struct A {
int a;
};
struct B {
A a;
int b;
};
I'm running pcyparser to parse it, with the following code
exploreStruct.py
#parse StructWithinStruct
from pycparser import parse_file
ast = parse_file(filename='..\StructWithinStruct.c')
ast.show()
As a result, I got the following:
Tracback (most recent call last):
File "exploreStruct.py", line 3, in <module>
ast = parse_file(filename='...\StructWithinStruct.c')
File "D:\...\pycparser\__init__.py", line 93, in parse_file
return parser.parse(text,filename)
File "D:\...\pycparser\c_parser.py", line 146, in parse
debug=debug_level)
File "D:\...\pycparser\yacc.py", line 331, in parse
return self.parseropt_notrack(input, lexer, debug, tracking, tokenfunc)
File "D:\...\pycparser\yacc.py", line 1181, in parseropt_notrack
tok=call_errorfunc(self.errorfunc, errtoken, self)
File "D:\...\pycparser\yacc.py", line 193, in call_errorfunc
r=errorfunc(token)
File "D:\...\pycparser\c_parser.py", line 1699, in p_error
column=self.clex.find_tok_column(p)))
File "D:\...\pycparser\plyparser.py", line 55, in _parse_error
raise ParseError("%s: %s % (coord, msg))
pycparser.plyparser.ParserError: D:...\StructWithinStruct.c:7:2: Before A
So, is pycparser can handle struct within struct, or not?
I thought this is some basic requirement, so I'm pretty sure that the problem lying in my configuration somewhere...
One more thing: I know that pcypareser author, #Eli Bendersky, says that one should use Clang to parse C++, but I will like to know if there's another option nowadays to parse C++ (preferably over Python), and is user-friendly.
Thanks.
Your struct declarations are not closed with a semicolon:
Additionally A itself is not a type name in C. In C++ A alone would suffice, but in C you need to add the struct keyword.
struct A {
int a;
};
struct B {
struct A a;
int b;
};
Or, you can declare a synonym with a typedef keyword:
struct A {
int a;
};
typedef struct A A;
or, shorter:
typedef struct A {
int a;
} A;
From that point the declaration
A a;
should compile properly.

How to use Pygtk in a C/C++ application?

I would like to integrate a simple Pygtk window in a C/C++ application (The reason being a previously designed GUI in pyGtk is to be integrated into a bigger GTK+ (in C) application)
I get Segmentation fault error
Here what i did :
=====> In python (tmp.py):
#!/usr/bin/python
#from gi.repository import Gtk, Gio
win=Gtk.Window()
win.connect("delete-event",Gtk.main_quit)
win.show_all()
Gtk.main()
======> In C/C++ (simple.cpp):
i want to just execute that little window
#include <Python.h>
int main(int argc, char *argv[])
{
Py_SetProgramName(argv[0]); /* optional but recommended */
Py_Initialize();
FILE *fp = fopen ("tmp.py", "r+");
PyObject *mainModule = PyImport_AddModule("__main__");
PyObject * subModules = PyList_New(0);
PyList_Append(subModules, PyString_FromString("Gtk"));
PyList_Append(subModules, PyString_FromString("Gio"));
PyObject *Gtkstuff = PyImport_ImportModuleEx("gi.repository",NULL,NULL,subModules);
PyObject *GtkMod =PyObject_GetAttr(Gtkstuff,PyString_FromString("Gtk"));
PyObject *GioMod =PyObject_GetAttr(Gtkstuff,PyString_FromString("Gio"));
PyModule_AddObject(mainModule, "Gtk", GtkMod);
PyModule_AddObject(mainModule, "Gio", GioMod);
PyRun_SimpleFile(fp,"tmp.py");
Py_Finalize();
return 0;
}
The way how i compile is :
g++ $(python-config --cflags) -o simple $(python-config --ldflags) ./simple.cpp
The output :
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/usr/lib64/python2.7/site-packages/gi/importer.py", line 68, in load_module
dynamic_module._load()
File "/usr/lib64/python2.7/site-packages/gi/module.py", line 291, in _load
overrides_modules = __import__('gi.overrides', fromlist=[self._namespace])
File "/usr/lib64/python2.7/site-packages/gi/overrides/Gtk.py", line 1502, in <module>
initialized, argv = Gtk.init_check(sys.argv)
AttributeError: 'module' object has no attribute 'argv'
Traceback (most recent call last):
File "tmp.py", line 5, in <module>
win=Gtk.Window()
File "/usr/lib64/python2.7/site-packages/gi/overrides/Gtk.py", line 415, in __init__
if not initialized:
NameError: global name 'initialized' is not defined
This works perfectly, the rest of the code doesn't make sense to me, since you can do all the initialization in the python script.
#include <Python.h>
int main(int argc, char *argv[])
{
Py_SetProgramName(argv[0]); /* optional but recommended */
Py_Initialize();
FILE *fp = fopen("tmp.py", "r");
if (fp == NULL)
return 2;
PyRun_SimpleFile(fp, "tmp.py");
Py_Finalize();
fclose(fp);
return 0;
}

How to use const in Cython

I have read in this link: https://github.com/cython/cython/wiki/FAQ#id35 that my Cython 0.20.1 should be able to support const.
However my following code does not compile:
cdef const double a = 2.5
print(a)
During compilation it says
test.pyx:5:5: Assignment to const 'a'
Traceback (most recent call last):
File "setup1.py", line 11, in <module>
ext_modules = cythonize(extensions)
File "X:\WinPython3\python-3.3.5.amd64\lib\site-packages\Cython\Build\Dependencies.py", line 785, in cythonize
cythonize_one(*args[1:])
File "X:\WinPython3\python-3.3.5.amd64\lib\site-packages\Cython\Build\Dependencies.py", line 902, in cythonize_one
raise CompileError(None, pyx_file)
Cython.Compiler.Errors.CompileError: test.pyx
const works for function arguments, but not for this construct because of how Cython compiles it to C.
cdef double a = 2.5
becomes
double __pyx_v_a;
/* lots of other declarations */
__pyx_v_a = 2.5;
and this wouldn't work with a const variable. In effect, you cannot use const in Cython in all the places were you can use it in C.

Categories

Resources