How to correctly use std::map<int, std::map<POINTER, STRUCT>> in SWIG? - swig

How to correctly use std::map<int, std::map<POINTER, STRUCT>> in SWIG when target is C#.
From documentation, tried using
namespace std
{
%template(map_POINTER_STRUCT) map<POINTER, STRUCT>;
%template(map_int_map_POINTER_STRUCT) std::map<int, std::map<POINTER, STRUCT>>;
}
But SWIG still gives error Error: Syntax error in input(3).

The error is due to SWIG and older C++ compilers mistaking >> for the right-shift operator. Insert a space:
%template(map_int_map_POINTER_STRUCT) std::map<int, std::map<POINTER, STRUCT> >;
^
here

Related

How to develop tool in C/C++ whose command interface is Tcl shell?

Suppose a tool X need to developed which are written in C/C++ and having Tcl commanline interface, what will the steps or way?
I know about Tcl C API which can be used to extend Tcl by writing C extension for it.
What you're looking to do is embedding Tcl (totally a supported use case; Tcl remembers that it is a C library) but still making something tclsh-like. The simplest way of doing this is:
Grab a copy of tclAppInit.c (e.g., this is the current one in the Tcl 8.6 source tree as I write this) and adapt it, probably by putting the code to register your extra commands, linked variables, etc. in the Tcl_AppInit() function; you can probably trim a bunch of stuff out simply enough. Then build and link directly against the Tcl library (without stubs) to get effectively your own custom tclsh with your extra functionality.
You can use Tcl's API more extensively than that if you're not interested in interactive use. The core for non-interactive use is:
// IMPORTANT: Initialises the Tcl library internals!
Tcl_FindExecutable(argv[0]);
Tcl_Interp *interp = Tcl_CreateInterp();
// Register your custom stuff here
int code = Tcl_Eval(interp, "your script");
// Or Tcl_EvalFile(interp, "yourScriptFile.tcl");
const char *result = Tcl_GetStringResult(interp);
if (code == TCL_ERROR) {
// Really good idea to print out error messages
fprintf(stderr, "ERROR: %s\n", result);
// Probably a good idea to print error traces too; easier from in Tcl
Tcl_Eval(interp, "puts stderr $errorInfo");
exit(1);
}
// Print a non-empty result
if (result[0]) {
printf("%s\n", result);
}
That's about all you need unless you're doing interactive use, and that's when Tcl_Main() becomes really useful (it handles quite a few extra fiddly details), which the sample tclAppInit.c (mentioned above) shows how to use.
Usually, SWIG (Simplified Wrapper and Interface Generator) is the way to go.
SWIG HOMEPAGE
This way, you can write code in C/C++ and define which interface you want to expose.
suppose you have some C functions you want added to Tcl:
/* File : example.c */
#include <time.h>
double My_variable = 3.0;
int fact(int n) {
if (n <= 1) return 1;
else return n*fact(n-1);
}
int my_mod(int x, int y) {
return (x%y);
}
char *get_time()
{
time_t ltime;
time(&ltime);
return ctime(&ltime);
}
Now, in order to add these files to your favorite language, you need to write an "interface file" which is the input to SWIG. An interface file for these C functions might look like this :
/* example.i */
%module example
%{
/* Put header files here or function declarations like below */
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
%}
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
At the UNIX prompt, type the following:
unix % swig -tcl example.i
unix % gcc -fpic -c example.c example_wrap.c \
-I/usr/local/include
unix % gcc -shared example.o example_wrap.o -o example.so
unix % tclsh
% load ./example.so example
% puts $My_variable
3.0
% fact 5
120
% my_mod 7 3
1
% get_time
Sun Feb 11 23:01:07 2018
The swig command produces a file example_wrap.c that should be compiled and linked with the rest of the program. In this case, we have built a dynamically loadable extension that can be loaded into the Tcl interpreter using the 'load' command.
Taken from http://www.swig.org/tutorial.html

Can't compile libpd with emmake (Emscripten SDK)

I'm trying to compile libpd to javascript or webassembly using emscripten sdk. According to some docs, if there is a Makefile, it can be compiled by using emmake make, (emconfigure is not used because there is no ./configure file), but I get the following error:
/home/ian/Documents/emsdk/emscripten/1.37.37/emcc.py -DPD -DHAVE_UNISTD_H -DUSEAPI_DUMMY -I./pure-data/src -I./libpd_wrapper -I./libpd_wrapper/util -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -fPIC -I"/usr/lib/jvm/default-java/include/linux" -DHAVE_LIBDL -ffast-math -funroll-loops -fomit-frame-pointer -O3 -DLIBPD_EXTRA -c -o pure-data/src/d_array.o pure-data/src/d_array.c
pure-data/src/d_array.c:523:2: error: No byte order defined
#error No byte order defined
^
1 error generated.
ERROR:root:compiler frontend failed to generate LLVM bitcode, halting
<integrado>: fallo en las instrucciones para el objetivo 'pure-data/src/d_array.o'
make: *** [pure-data/src/d_array.o] Error 1
Any ideas? Do you think is possible to compile this library?
UPDATE: After tweaking every complaining file as suggested in #zakki 's answer
I get another error:
libpd_wrapper/util/ringbuffer.c:18:12: fatal error: 'stdatomic.h' file not found
#include <stdatomic.h>
That file have this content:
#if __STDC_VERSION__ >= 201112L // use stdatomic if C11 is available
#include <stdatomic.h> // HERE IS WHERE ERROR GOES
#define SYNC_FETCH(ptr) atomic_fetch_or((_Atomic int *)ptr, 0)
#define SYNC_COMPARE_AND_SWAP(ptr, oldval, newval) \
atomic_compare_exchange_strong((_Atomic int *)ptr, &oldval, newval)
//Some other definitions that I didn't put here
I read some threads some time ago about this problem with C++11, how can i fix this?
UPDATE 2: After adding && !defined(__EMSCRIPTEN__) now is able to compile, but I'm getting this warning that I don't understand:
WARNING:root:Dynamic libraries (.so, .dylib, .dll) are currently not
supported by Emscripten. For build system emulation purposes,
Emscripten will now generate a static library file (.bc) with the
suffix '.so'. For best practices, please adapt your build system to
directly generate a static LLVM bitcode library by setting the output
suffix to '.bc.')
Emscripten has endian.h. So add defined(__EMSCRIPTEN__) to ifdef.
#if defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) || \
defined(ANDROID) || defined(__EMSCRIPTEN__)
#include <endian.h>
#endif
Second, it seems like Emscripten bug.
#if __STDC_VERSION__ >= 201112L && !defined(__EMSCRIPTEN__)

Tk/Tcl extensions: error while compile BLT

I am compile BLT under OS X 10.10.5, while I make after ./configure, some error occur here:
FDSM_lhn#Nirvana:~/Downloads/blt2.4z$ sudo make -I/opt/X11/include
Password:
(cd src; /Applications/Xcode.app/Contents/Developer/usr/bin/make all)
gcc -c -Wall -O6 -I. -I. bltAlloc.c
warning: optimization level '-O6' is not supported; using '-O3' instead
In file included from bltAlloc.c:1:
In file included from ./bltInt.h:80:
./bltNsUtil.h:50:20: error: conflicting types for 'Tcl_FindCommand'
EXTERN Tcl_Command Tcl_FindCommand _ANSI_ARGS_((Tcl_Interp *interp,
^
/usr/local/include/tclDecls.h:1486:20: note: previous declaration is here
EXTERN Tcl_Command Tcl_FindCommand(Tcl_Interp *interp, const char *name,
^
In file included from bltAlloc.c:1:
In file included from ./bltInt.h:80:
./bltNsUtil.h:67:23: error: conflicting types for 'Tcl_CreateNamespace'
EXTERN Tcl_Namespace *Tcl_CreateNamespace _ANSI_ARGS_((Tcl_Interp *interp,
^
/usr/local/include/tclDecls.h:1460:24: note: previous declaration is here
EXTERN Tcl_Namespace * Tcl_CreateNamespace(Tcl_Interp *interp,
^
In file included from bltAlloc.c:1:
In file included from ./bltInt.h:80:
./bltNsUtil.h:72:23: error: conflicting types for 'Tcl_FindNamespace'
EXTERN Tcl_Namespace *Tcl_FindNamespace _ANSI_ARGS_((Tcl_Interp *interp,
^
/usr/local/include/tclDecls.h:1482:24: note: previous declaration is here
EXTERN Tcl_Namespace * Tcl_FindNamespace(Tcl_Interp *interp,
^
In file included from bltAlloc.c:1:
In file included from ./bltInt.h:80:
./bltNsUtil.h:75:12: error: conflicting types for 'Tcl_Export'
EXTERN int Tcl_Export _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Namespace *nsPtr,
^
/usr/local/include/tclDecls.h:1469:13: note: previous declaration is here
EXTERN int Tcl_Export(Tcl_Interp *interp, Tcl_Namespace *nsPtr,
^
1 warning and 4 errors generated.
make[1]: *** [bltAlloc.o] Error 1
make: *** [all] Error 2
What should I do to avoid this?
You're working with an elderly codebase, so some surgery is required. Alas.
The four offending declarations in bltNsUtil.h need to be removed as Tcl now declares them properly; Tcl_FindCommand, Tcl_CreateNamespace, Tcl_FindNamespace and Tcl_Export are part of Tcl's public API and have been for years. (The problem declarations are on lines 50, 67, 72, and 75, plus probably one or two lines further in each case.)
Also, you're recommended to not use sudo while doing the build itself, but rather just when doing the install afterwards. Mere compilation of the code shouldn't require elevated permissions.

swig error: Extraneous #endif

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.

SWIG errors because of preprocessor directive

We have a vendor that has provided us a C++ library and headers, that I'm trying to wrap using SWIG. It appears that they are being too clever by a half with the preprocessor directives:
// top.h
#define DECLARE_WITH_COMMA(a) a,
and then
// foo.h
#include "top.h"
#define MY_TYPES(d) \
d(One) \
d(Two) \
d(Three) \
NumElems
enum MyTypes {
MY_TYPES(DECLARE_WITH_COMMA)
};
Which is all a longwinded way of saying that when I try to run SWIG (version 2.0.4) on "foo.h", I get:
foo.h:12: Error: Syntax error in input(1).
So my question is what are my options here, given that I probably don't want to change the vendor-supplied headers?
SWIG doesn't recurse into nested headers by default, so your .i file should look something like:
%module mymod
%{
#include "foo.h"
%}
%include "top.h"
%include "foo.h"
There is also a SWIG switch:
-includeall - Follow all #include statements
but if you have system headers that may do more than you intend.