Parsing struct within struct in C using pycparser? - python

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.

Related

How can I call a c++ function using 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.

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

How to call a python file using Tensorflow library in C++ environment?

When I tried to call a python file using Tensorflow library in C++ environment, I got a problem like this. I have no idea how to solve it.
This is my C++ code.
#include <Python.h>
#include <iostream>
int main(int argc, wchar_t** argv)
{
const char* picpath ="/home/senius/Pictures/zys.jpg";
Py_Initialize();
//PySys_SetArgv(argc, argv);
//PyRun_SimpleString("import sys\nprint sys.argv");
if ( !Py_IsInitialized() ) {
return -1;
}
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('/home/senius/Python/Ctensor/')");
PyObject* pMod = NULL;
PyObject* pFunc = NULL;
PyObject* pParm = NULL;
PyObject* pRetVal = NULL;
int iRetVal = -999;
const char* modulName="classify"; //这个是被调用的py文件模块名字
pMod = PyImport_ImportModule(modulName);
if(!pMod)
{
std::cout<<"Import module failed!";
PyErr_Print();
return -1;
}
const char* funcName="evaluate"; //这是此py文件模块中被调用的函数名字
pFunc = PyObject_GetAttrString(pMod, funcName);
if(!pFunc)
{
std::cout<<"Import function failed!";
return -2;
}
pParm = PyTuple_New(1);
PyTuple_SetItem(pParm, 0, Py_BuildValue("s",picpath));//传入的参数,是图片的路径
pRetVal = PyEval_CallObject(pFunc, pParm);//这里开始执行py脚本
PyArg_Parse(pRetVal, "i", &iRetVal);//py脚本返回值给iRetVal
//PyErr_Print();
std::cout<<iRetVal;
return iRetVal;
}
This is my python code.
from PIL import Image
import numpy as np
import sys
import tensorflow as tf
def evaluate(pic):
if not hasattr(sys, 'argv'):
sys.argv = ['']
image = Image.open(pic)
image = image.resize([256, 256])
image_array = np.array(image)
max_index = np.argmax([1, 2, 32])
return max_index
Once I import Tensorflow in python code, there will be a error. If I don't import Tensorflow, error disappears.
Error information is as followed.
Import module failed!Traceback (most recent call last):
File "/home/senius/Python/Ctensor/classify.py", line 4, in <module>
import tensorflow as tf
File "/home/senius/anaconda3/lib/python3.6/site- packages/tensorflow/__init__.py", line 24, in <module>
from tensorflow.python import *
File "/home/senius/anaconda3/lib/python3.6/site-packages/tensorflow/python/__init__.py", line 63, in <module>
from tensorflow.python.framework.framework_lib import *
File "/home/senius/anaconda3/lib/python3.6/site-packages/tensorflow/python/framework/framework_lib.py", line 76, in <module>
from tensorflow.python.framework.ops import Graph
File "/home/senius/anaconda3/lib/python3.6/site-packages/tensorflow/python/framework/ops.py", line 37, in <module>
from tensorflow.python.eager import context
File "/home/senius/anaconda3/lib/python3.6/site-packages/tensorflow/python/eager/context.py", line 28, in <module>
from tensorflow.python.platform import app
File "/home/senius/anaconda3/lib/python3.6/site-packages/tensorflow/python/platform/app.py", line 23, in <module>
from tensorflow.python.platform import flags
File "/home/senius/anaconda3/lib/python3.6/site-packages/tensorflow/python/platform/flags.py", line 26, in <module>
_global_parser = _argparse.ArgumentParser()
File "/home/senius/anaconda3/lib/python3.6/argparse.py", line 1622, in __init__
prog = _os.path.basename(_sys.argv[0])
AttributeError: module 'sys' has no attribute 'argv'
You import the tensorflow module - and during that import it attempts to use sys.argv (as you can see from your stack trade) and then sometime later in some function, you have
if not hasattr(sys, 'argv'):
sys.argv = ['']`
which is the workaround to this error - but it can never be called because the import failed.
The fix is to move this to before you import the tensorflow module

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