swig error: Extraneous #endif - swig

When I executed the swig command on my .i file, I am getting an error on an include file.
The error says:
../include/example.h: Error: Extraneous #endif.
The contents of the example.h file is as below:
#ifndef EXAMPLE_H
#define EXAMPLE_H
namespace my_example {
class BaseExample {
public:
virtual ~BaseExample() {}
};
}
#endif /* EXAMPLE_H */
In the above code, the #endif correctly matches with #ifndef.
So, why is swig reporting "Extraneous #endif." ?

I finally found the problem and solved it.
I think, the file had BOM marks in the end of file.
So, I executed
:set nobomb
inside my vim editor, and the error went away.

Related

Having trouble Generating Wrapper function using Swig for C++ template

I am trying to use swig to generate interface on some existing C++ methods. I am referring to the following link for practice to generate on c++ template methods
https://valelab4.ucsf.edu/svn/3rdpartypublic/swig/Examples/python/template/
File : example.h
// Some template definitions
template<class T> T max(T a, T b) { return a>b ? a : b; }
template<class T> class vector {
T *v;
int sz;
public:
vector(int _sz) {
v = new T[_sz];
sz = _sz;
}
T &get(int index) {
return v[index];
}
void set(int index, T &val) {
v[index] = val;
}
#ifdef SWIG
%extend {
T getitem(int index) {
return $self->get(index);
}
void setitem(int index, T val) {
$self->set(index,val);
}
}
#endif
};
File : example.i
%module example
%{
#include "example.h"
%}
/* Let's just grab the original header file here */
%include "example.h"
/* Now instantiate some specific template declarations */
%template(maxint) max<int>;
%template(maxdouble) max<double>;
%template(vecint) vector<int>;
%template(vecdouble) vector<double>;
setup.py
from distutils.core import setup, Extension
#name of module
name = "example"
#version of module
version = "1.0"
# specify the name of the extension and source files
# required to compile this
ext_modules = Extension(name='_example',sources=["example.i","example.h"])
setup(name=name,
version=version,
ext_modules=[ext_modules])
step 1: compile module
python setup.py build_ext
step 2: install in the current directory
python setup.py install --install-platlib=.
I am seeing the following errors as the output
python setup.py build_ext
running build_ext
building '_example' extension
swigging example.i to example_wrap.c
swig -python -o example_wrap.c example.i
example.h:5: Warning 301: class keyword used, but not in C++ mode.
example.h:5: Error: Syntax error - possibly a missing semicolon.
error: command 'swig' failed with exit status 1
Use the following in setup.py to pass the -c++ option to SWIG. Also remove example.h from sources or the compiler tries to compile the header. It's already included in the generated file.
ext_modules = Extension(name='_example', sources=["example.i"], swig_opts=['-c++'])

boost.log error occured while using sink.set_filter

I use boost.log for my project.
But when I tried to set filter for sinks, compilation errors came.
code are simple:
BOOST_LOG_ATTRIBUTE_KEYWORD(MyTag, "My_Tag", std::string);
BOOST_LOG_INLINE_GLOBAL_LOGGER_CTOR_ARGS(
my_logger
, boost::log::sources::channel_logger_mt< >
, (boost::log::keywords::channel = "default"))
typedef boost::log::sinks::synchronous_sink<
boost::log::sinks::text_ostream_backend > TextSink;
boost::shared_ptr< TextSink > logSink = boost::make_shared< TextSink >();
auto backSink = boost::make_shared<std::ofstream>("default.log");
!!! compilation error, no add_attribute in channel_logger !!!
my_logger::get().add_attribute("My_Tag"
, boost::log::attributes::constant<String>("My_Tag"));
logSink->set_filter(
boost::log::expressions::has_attr(MyTag)
!!! compilation error, invalid operand expression between attribute_actor and std::string !!!
&& boost::log::expressions::attr<std::string>("My_Tag")==std::string("My_Tag")
!!! compilation error, invalid operand expression between attribute_keyword<tag::MyTag> and char[7] !!!
&& MyTag=="My_Tag"
I also tried to define filter function, but got following error:
bool my_filter(
boost::log::value_ref< std::string
!!! compilation error, no tag_attr in boost::log::expressions::tag !!!
, boost::log::expressions::tag::tag_attr > const& tag)
{
return level >= warning || tag == "IMPORTANT_MESSAGE";
}
By the way, I also have following error, but this error will disappear if all other compilation errors were solved.
!!! no open_record in severity_logger_mt !!!
BOOST_LOG_SEV(slg, normal) << "A regular message";
could anyone help me?
full code :
#include <boost/phoenix/operator.hpp>
#include <boost/log/sources/channel_logger.hpp>
#include <boost/log/attributes.hpp>
#include <boost/log/attributes/attribute.hpp>
#include <boost/log/attributes/attribute_cast.hpp>
#include <boost/log/keywords/filter.hpp>
#include <boost/log/expressions/predicates.hpp>
#include <boost/log/expressions/attr_fwd.hpp>
#include <boost/log/expressions/attr.hpp>
#include <boost/log/expressions.hpp>
#include <boost/log/sinks.hpp>
BOOST_LOG_INLINE_GLOBAL_LOGGER_CTOR_ARGS(
my_channel_logger
, boost::log::sources::channel_logger_mt< >
, (boost::log::keywords::channel = "channel"))
BOOST_LOG_ATTRIBUTE_KEYWORD(MyTag, "My_Tag", std::string);
typedef boost::log::sinks::synchronous_sink<
boost::log::sinks::text_ostream_backend > TextSink;
static boost::shared_ptr< TextSink > logSink = boost::make_shared< TextSink >();
static auto backSink = boost::make_shared<std::ofstream>("output.log");
void func() {
!!! compilation error, no 'open_record' in channel_logger_mt !!!
BOOST_LOG_CHANNEL(my_channel_logger::get(), "channel")<<"channel log";
!!! compilation error, no add_attribute in channel_logger !!!
my_channel_logger::get().add_attribute("My_Tag"
, boost::log::attributes::constant<String>("My_Tag"));
}
compilation error for no open_record in channel_logger_mt:
***.cpp:87:5: error: no member named 'open_record' in 'boost::log::v2_mt_nt6::sources::channel_logger_mt<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >'
channel_feature.hpp:236:41: note: expanded from macro 'BOOST_LOG_CHANNEL'
channel_feature.hpp:231:5: note: expanded from macro 'BOOST_LOG_STREAM_CHANNEL'
record_ostream.hpp:566:5: note: expanded from macro 'BOOST_LOG_STREAM_WITH_PARAMS'
record_ostream.hpp:555:50: note: expanded from macro 'BOOST_LOG_STREAM_WITH_PARAMS_INTERNAL'
compilation error for no add_attribute in channel_logger_mt:
***.cpp:76:31: error: no member named 'add_attribute' in 'boost::log::v2_mt_nt6::sources::channel_logger_mt<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >'
Most likely, you're missing #includes in your code.
!!! compilation error, no add_attribute in channel_logger !!!
my_logger::get().add_attribute("My_Tag"
, boost::log::attributes::constant<String>("My_Tag"));
add_attribute is defined by basic_composite_logger, from which channel_logger_mt derives. You need to include boost/log/sources/channel_logger.hpp.
!!! compilation error, invalid operand expression between attribute_actor and std::string !!!
&& boost::log::expressions::attr<std::string>("My_Tag")==std::string("My_Tag")
!!! compilation error, invalid operand expression between attribute_keyword<tag::MyTag> and char[7] !!!
&& MyTag=="My_Tag"
Most likely, you're missing an include of boost/phoenix/operator.hpp. Or you can include boost/log/expressions.hpp, which automatically includes it for you.
!!! no open_record in severity_logger_mt !!!
BOOST_LOG_SEV(slg, normal) << "A regular message";
Same as with channel_logger_mt. You need to include boost/log/sources/severity_logger.hpp.
Note that for every component in the docs, there is a list of associated Boost.Log headers in the very beginning of the section. Here is an example for the severity logger.
Update on 2019-07-03:
Your full code compiles, if the following includes are added:
#include <string>
#include <fstream>
#include <boost/smart_ptr/shared_ptr.hpp>
#include <boost/smart_ptr/make_shared_object.hpp>
#include <boost/log/sources/global_logger_storage.hpp>
#include <boost/log/sources/record_ostream.hpp>
I also had to remove the "!!!" lines and use std::string instead of String in the constant attribute.
In general, you have to include a header for every component you use in your code.

How to handle redefinition of Macro?

My C code is like bellow.
// file.c
#include <stdio.h>
#define value 10
#define value 20
void func()
{
printf("%d\n",value);
}
My Interface file is like bellow.
//sample.i
%module sample
%{
#include "func.c"
%}
%include "func.c"`
When I run the command "swig -python sample.i", I am getting the error like bellow.
Macro 'value' redefined. The previous definition of 'value' is there.
How to handle this?
Interesting that swig considers it an error, but the compiler (mine anyway) considers it a warning. If you can't fix the header, you can do:
//sample.i
%module sample
%{
#include "func.c"
%}
#define value 20
void func()
{
printf("%d\n",value);
}
Basically, expand the header file inline and remove the offending line from swig processing. Otherwise, fix the header.

package require with static lib

I am working on app which uses tcl package implemented in C++ and linked as static library (app is developed long time ago). It does following:
// Library code
extern "C" int testlib_SafeInit _ANSI_ARGS_((Tcl_Interp *interp))
{
return Tcl_PkgProvide(interp, "testlib", "1.6");
}
extern "C" int testlib_Init _ANSI_ARGS_((Tcl_Interp *interp))
{
return testlib_SafeInit(interp);
}
// Application code
extern "C" int testlib_SafeInit _ANSI_ARGS_((Tcl_Interp *interp));
extern "C" int testlib_Init _ANSI_ARGS_((Tcl_Interp *interp));
int main()
{
Tcl_Interp* interp = Tcl_CreateInterp();
Tcl_Init(interp);
Tcl_PkgProvide(interp, "testlib", "1.6");
Tcl_StaticPackage(interp, "testlib", testlib_Init, testlib_SafeInit);
Tcl_Eval(interp, "package require testlib");
std::cout << "Res = " << Tcl_GetStringResult(interp);
return 0;
}
When I am removing line Tcl_PkgProvide(interp, "testlib", "1.6"); from main, package becomes invisible. Also I have noticed that testlib_Init and testlib_SafeInit are not called. I am expecting that they must be called from package require testlib. As I understand from docs each package must have pkgIndex.tcl in auto_path or tcl_pkgPath which must contain line
(package ifneeded testlib 1.6 {load {} testlib}), but here both variables does not contain such index file.
Is this a correct way of providing packages? Is there a documentation related with providing packages using static libraries?
Well, the simplest technique for statically providing a package is to just install it directly. The package init code should be the one calling Tcl_PkgProvide — you don't do so from main() usually — and you probably don't need Tcl_StaticPackage at all unless you're wanting to install the code into sub-interpreters.
int main(int argc, char*argv[])
{
Tcl_FindExecutable(argv[0]);
Tcl_Interp* interp = Tcl_CreateInterp();
Tcl_Init(interp);
testlib_Init(interp);
// OK, setup is now done
Tcl_Eval(interp, "package require testlib");
std::cout << "Res = " << Tcl_GetStringResult(interp) << "\n";
return 0;
}
However, we can move to using Tcl_StaticPackage. That allows code to say “instead of loading a DLL with this sort of name, I already know that code: here are its entry points”. If you are doing that, you need to also install a package ifneeded script; those are done through the script API only.
int main(int argc, char*argv[])
{
Tcl_FindExecutable(argv[0]);
Tcl_Interp* interp = Tcl_CreateInterp();
Tcl_Init(interp);
Tcl_StaticPackage(interp, "testlib", testlib_Init, testlib_SafeInit);
Tcl_Eval(interp, "package ifneeded testlib 1.6 {load {} testlib}");
// OK, setup is now done
Tcl_Eval(interp, "package require testlib");
std::cout << "Res = " << Tcl_GetStringResult(interp) << "\n";
return 0;
}
The testlib in the load call needs to match the testlib in the Tcl_StaticPackage call. The testlib in the package require, package ifneeded and Tcl_PkgProvide also need to all match (as do the occurrences of 1.6, the version number).
Other minor issues
Also, you don't need to use the _ANSI_ARGS_ wrapper macro. That's utterly obsolete, for really ancient and crappy compilers that we don't support any more. Just replace _ANSI_ARGS_((Tcl_Interp *interp)) with (Tcl_Interp *interp). And remember to call Tcl_FindExecutable first to initialise the static parts of the Tcl library. If you don't have argv[0] available to pass into it, use NULL instead; it affects a couple of more obscure introspection systems on some platforms, but you probably don't care about them. However, initialising the library overall is very useful: for example, it lets you make sure that the filesystem's filename encoding scheme is correctly understood! That can be a little important to code…

including tk.h and tcl.h in c program

i am working on an ubuntu system. My aim is to basically make an IDE in C language using GUI tools from TCL/TK. I installed tcl 8.4, tk8.4, tcl8.4-dev, tk8.4-dev and have the tk.h and tcl.h headers file in my system. But, when I am running a basic hello world program it's showing a hell lot of errors.
#include "tk.h"
#include "stdio.h"
void hello() {
puts("Hello C++/Tk!");
}
int main(int, char *argv[])
{
init(argv[0]);
button(".b") -text("Say Hello") -command(hello);
pack(".b") -padx(20) -pady(6);
}
Some of the errors are
tkDecls.h:644: error: expected declaration specifiers before ‘EXTERN’
/usr/include/libio.h:488: error: expected ‘)’ before ‘*’ token
In file included from tk.h:1559,
from new1.c:1:
tkDecls.h:1196: error: storage class specified for parameter ‘TkStubs’
tkDecls.h:1201: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘*’ token
/usr/include/stdio.h:145: error: storage class specified for parameter ‘stdin’
tk.h:1273: error: declaration for parameter ‘Tk_PhotoHandle’ but no such parameter
Can anyone please tell me how can I rectify these errors? Please help...
Are you writing Tcl or C there? Confusion over that is what's causing all those errors.
Assuming you're just writing Tcl to pop up a Tk GUI that does something, you make a file called hello.tcl with this contents:
package require Tk
proc hello {} {
puts "Hello C++/Tk!"
}
button .b -text "Say Hello" -command hello
pack .b -padx 20 -pady 6
Then you run it with this:
wish hello.tcl
To run this from within a C program, you need to do more work.
#include <tcl.h>
#include <tk.h>
int main(int argc, char **argv) {
Tcl_Interp *interp;
Tcl_FindExecutable(argv[0]);
interp = Tcl_CreateInterp();
Tcl_Eval(interp,
"package require Tk\n"
"proc hello {} {\n"
"puts \"Hello C++/Tk!\"\n"
"}\n"
"button .b -text \"Say Hello\" -command hello\n"
"pack .b -padx 20 -pady 6\n");
Tk_MainLoop();
Tcl_DeleteInterp(interp);
return 0;
}
The string literal, broken up over several lines, ought to be fairly recognizable from before. You might want to use Tcl_EvalFile instead to bring in the script to run from another file, because writing all those backslashes for quoting gets tedious. There are also alternatives to Tk_MainLoop, all of which involve Tcl_DoOneEvent somewhere (Tk_MainLoop is a wrapper round that too) but I can't tell what's best for you there on the evidence so far.
Compile the above code, linking against both libtk and libtcl in that order. I can't remember if you have to explicitly link against the X11 library too, or whether linking against Tk will be enough.