Preprocessor for_each witin SWIG interface - swig

I've been using the REFLECTABLE macro from this answer in my C++ header file, which looks like:
#ifndef TIMER_H
#define TIMER_H
// From the linked question, but (deliberately) ignored by SWIG here,
// only relevant is as much as it defines REFLECTABLE for other preprocessors
#include "reflection.hh"
struct Timer {
REFLECTABLE (
(float) startTime,
(float) endTime,
)
};
#endif
The SWIG preprocessor doesn't follow #include and doesn't handle the definition of REFLECTABLE from the linked question anyway, so my plan is to ignore that entirely and replace it with a more appropriate SWIG specific definition of REFLECTABLE.
My goal is for the SWIG preprocessor to expand Timer as though there was nothing special going on, i.e.:
struct Timer {
float startTime;
float endTime;
};
To that end I have written a simple reflection.i that makes a recursive call to a %define SWIG macro:
#define REM(...) __VA_ARGS__
#define PAIR(x) REM x
%define EXPAND(tail, ...)
PAIR(tail);
EXPAND(__VA_ARGS__)
%enddef
#define REFLECTABLE(...) EXPAND(__VA_ARGS__)
That I can use in test.i:
%module test
%include "reflection.i"
%include "timer.h"
When we run swig -python -Wall -E test.i to inspect the result of running this through the SWIG preprocessor it almost works, but the definition at the end of recursion doesn't quite match what I'd like:
struct Timer {
/*#SWIG:reflection.i,4,EXPAND#*/
float startTime;
/*#SWIG:reflection.i,4,EXPAND#*/
float endTime;
EXPAND
};
The problem is that recursion gets terminated by the bareword EXPAND when ___VA_ARGS__ is empty. I looked at using map.h from this answer, but that also doesn't work with the SWIG preprocessor.
How can I modify my definition of REFLECTABLE so that the SWIG preprocessor just generates the flat structure I'm looking for?

I came up with a solution in the end that required two changes:
There's more indirection to the recursion, we paste two tokens together to get the token EXPAND_STOP or EXPAND_MORE, depending on whether or not the __VA_ARGS__ is empty during this evaluation. This selection takes place because SWIG evaluates
#define STOP(...) MORE
as MORE when there are arguments, but simply as STOP when there are no arguments.
The TOKEN macro then adds the required indirection for the token paste operator to work.
There's a fake first argument to both EXPAND_MORE and EXPAND_STOP that prevents the same behaviour from stopping us eating the call to EXPAND_STOP with no arguments.
#define REM(...) __VA_ARGS__
#define PAIR(x) REM x
#define TOKEN_(x,y) x##y
#define TOKEN(x,y) TOKEN_(x, y)
#define STOP(...) MORE
%define EXPAND_MORE(fake, ...)
EXPAND(__VA_ARGS__)
%enddef
#define EXPAND_STOP(fake, ...)
%define EXPAND(tail, ...)
PAIR(tail);
TOKEN(EXPAND_, STOP(__VA_ARGS__)) ## (fake, ##__VA_ARGS__)
%enddef
#define REFLECTABLE(...) EXPAND(__VA_ARGS__)
Although possibly not the most elegant solution this is tested and working with SWIG 3.0.2.

Related

Can I use vararg functions in CUDA device-side code?

I know that we can't write CUDA kernels with a variable number of parameters:
Is it possible to have a CUDA kernel with varying number of parameters?
(at least not in the C varargs sense; we can use C++ variadic templates.)
But what about non-kernel device-side code, i.e. __device__ functions? Can these be varargs functions?
Yes, we can write varargs device-side functions.
For example:
#include <stdio.h>
#include <stdarg.h>
__device__ void foo(const char* str, ...)
{
va_list ap;
va_start(ap, str);
int arg = va_arg(ap, int); // making an assumption here
printf("str is \"%s\", first va_list argument is %d\n", str, arg);
}
This compiles fine with NVCC - and works, provided you actually pass a null-terminated string and an int. I would not be surprised if CUDA's printf() itself were implemented this way.

Cython compiling error: Saying that Array is a Struct

This is a minimally reproducible version of my Cython error. The code runs in C++.
The compiler is telling me error C2088 that "+= is illegal for struct". However, it is being passed an array.
The pyx file:
from libc.stdint cimport uint32_t as Card
from cpython cimport array
import array
cdef extern from "ace_eval.h":
void ACE_addcard(h, Card c)
def create_hand():
cdef array.array h = array.array('I',[0, 0, 0, 0, 0])
ACE_addcard(h, 257)
return h
The function imported from the header is:
#define ACE_addcard(h,c) h[c&7]+=c,h[3]|=c
I have also tried declaring my arrays using
cdef Card h[5]
array.array is a Python object that is ultimately compiled into a struct (so this is what C++ sees). Element access to it is controlled at a Python level by __getitem__ and __setitem__, which are compiled by Cython into C API function calls. When Cython sees code for an array being manipulated it'll generate the appropriate C API function calls. You code using C++ #define statements attempts to manipulate it at C++ compile time and prevents Cython from knowing what's going on.
Ideally you should be using "typed memoryviews" which give Cython quicker access to the array (but will still not work with the C++ #define since this is applied after Cython has processed the file):
cdef int[::1] h = array.array('I',[0, 0, 0, 0, 0]) # you may have to change the type long... I haven't tested it
h[257&7]+=257
h[3]|=257
If you absolutely insist on using macros instead then they need to take something with a C++ array interface. A pointer is probably the easiest option and can be got from:
cdef int* h_ptr = &h[0]
#DavidW 's second way of
cdef Card h[5]
h[:] = [0, 0, 0, 0, 0]
cdef Card* h_ptr = &h[0]
also worked once I also adjusted my cdef like so to accept the pointer. Note that the function in the #define macro is not changed and does not have return type specified.
cdef extern from "ace_eval.h":
void ACE_addcard(Card* h, Card c)
This allowed me to pass any of my arrays over flawlessly.
This is actually what it says in the docs, but it was a bit obtuse to me - hopefully my explanation helps someone else.
https://cython.readthedocs.io/en/latest/src/userguide/external_C_code.html
If the header file defines a function using a macro, declare it as though it were an ordinary function, with appropriate argument and result types.

How do I write variadic templates, that can't accept zero arguments?

Here is a variadic template that prints parameters.
#include <string>
#include <iostream>
void Output() {
std::cout<<std::endl;
}
template<typename First, typename ... Strings>
void Output(First arg, const Strings&... rest) {
std::cout<<arg<<" ";
Output(rest...);
}
int main() {
Output("I","am","a","sentence");
Output("Let's","try",1,"or",2,"digits");
Output(); //<- I do not want this to compile, but it does.
return 0;
}
Is there a way to get this functionality without having the "no parameter" call work, and without having to write two functions every time?
You might want to keep the separation of the first and the rest of the parameters, you can use:
template<typename First, typename ... Rest>
void Output(First&& first, Rest&&... rest) {
std::cout << std::forward<First>(first);
int sink[]{(std::cout<<" "<<std::forward<Rest>(rest),0)... };
(void)sink; // silence "unused variable" warning
std::cout << std::endl;
}
Note that I used perfect forwarding to avoid copying any parameters. The above has the additional benefit to avoid recursion and therefore is likely to produce better (faster) code.
The way I wrote sink also guarantees that the expressions expanded from rest are evaluated left-to-right - which is important when compared to the naïve approach of just writing a helper function template<typename...Args>void sink(Args&&...){}.
Live example
Call the function from a forwarding type function and have a static_assert like this:
template <typename ... Args>
void forwarder(Args ... args) {
static_assert(sizeof...(args),"too small");
Output(args...);
}
As far as I see there are two questsions:
How to avoid Output() calls with no parameters.
Is there a simpler way to end the compile time recursion?
My solution to item 1 is as follows:
template<typename T>
void Output(const T & string) {
std::cout<<string<<std::endl;
}
template<typename First, typename ... Strings>
void Output(const First & arg, const Strings & ... rest) {
std::cout<<arg<<" ";
Output(rest...);
}
Basically, instead of ending the recursion when the template list is empty, I end it when it only contains one type. There is one difference between the above and the code from the question: if does not output any space after the last item. Instead it just outputs the newline.
For question number two see the answer by Daniel Frey above. I really liked this solution, although it took some time to grasp it (and I upvoted the answer). At the same time I find that it makes the code harder to read/understand and therefore harder to maintain. Currently I would not not use that solution in anything but small personal code snippets.

Use Tcl library with C code gets errors

softwarre: ActiveState ActiveTcl 8.5.13.296436/Win7/DEV C++ 5.4.1.
ActiveTcl is installed at D:/TCL/.
error information:
E:\src\c\tcl\main.oIn function `Tcl_AppInit':
8E:\src\c\tcl\main.cundefined reference to `_imp__Tcl_Init'
E:\src\c\tcl\main.oIn function `main':
14E:\src\c\tcl\main.cundefined reference to `_imp__Tcl_Main'
E:\src\c\tcl\collect2.exe[Error] ld returned 1 exit status
26E:\src\c\tcl\Makefile.winrecipe for target 'tcl_test.exe' failed
c source code:
#include <stdio.h>
#include <stdlib.h>
#include <tcl.h>
#include <tk.h>
int Tcl_AppInit(Tcl_Interp *interp)
{
return (Tcl_Init(interp) == (TCL_ERROR))?TCL_ERROR:TCL_OK;
}
int main(int argc, char** argv)
{
printf("--- Tcl Third-Party Shell Start ---\n");
Tcl_Main(argc, argv, Tcl_AppInit);
printf("--- Tcl Third-Party Shell End ---\n");
return 0;
}
In order to access those functions (notably, Tcl_Main) you must link your code against the Tcl DLL (which I think will be tcl85.dll in your installation); it's not a symbol that is exported through Tcl's stub linking mechanism. I don't know exactly how you do that on Windows (nor exactly where it will be located) but instructing your build environment to use the DLL should not be too difficult.
FWIW, Tcl_Init always returns either TCL_OK (i.e., 0) or TCL_ERROR (i.e., 1). You can just return the value directly from your AppInit function if you're not going to install your own commands and functionality after basic initialization.
After playing around a bit I could reproduce and solve this in Visual Studio.
You just have to add D:\Tcl\lib\tcl86.lib to the "Additional Dependencies" under "Linker/Input".
This solved the problem for me.
Edit
You could either pass Tcl_Init to Tcl_Main (If you don't have to do any specific initialization) or just return the result of Tcl_Init like this:
int Tcl_AppInit(Tcl_Interp *interp)
{
return Tcl_Init(interp);
}

Implement support for std::vector without std_vector.i

Okay, I've already asked 2 questions about my problem and despite the fact that the replies were really helpful, I am not able to find an optimal solution for my problem. Let me explain my main objective/problem now.
Due to some constraints I can't use std_vector.i in my swig interface, but I need to use a C++ object of (vector of vectors of string)vector<vector<string>> in Python. I implemented a solution where I am converting whole vector<vector<string> > to Python "List of Lists" wherein I am doing the following conversions:
each C++ string to Python String using PyString_FromString()
each vector<string> to Python Lists l1, l2, l3, l4...
and finally vector<vector<string> > to a Python List containing l1, l2, l3, l4.. as elements.
Although, the above solution works fine and I am able to access the string values in Python but this solution doesn't look optimal to me.
I would prefer a class (without using std_vector.i) whose object I can pass as a function argument to be populated with values and after returning from the function I should be able to access the values using ob[0][0] etc. In this way I will have to make only one conversion (C++ string to python string) ,for each value accessed, in __getitem__. But I don't know how to define a class representing vector<vector<string> > in Python without using %template.
I've put together an example of a minimal wrapper for std::vector<std::vector<std::string > > which works without including any extra SWIG files (e.g. std_vector.i and std_string.i).
I also put together a small header file to test my implementation with:
#include <vector>
#include <string>
#include <algorithm>
#include <iterator>
#include <iostream>
inline void print_vec(const std::vector<std::string>& v) {
std::copy(v.begin(),v.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
}
inline void print_vec_vec(const std::vector<std::vector<std::string> >& v) {
std::for_each(v.begin(),v.end(),print_vec);
}
std::vector<std::vector<std::string> > make() {
static std::vector<std::string> test1;
static std::vector<std::string> test2;
static std::vector<std::vector<std::string> > ret;
test1.push_back("hello");
test2.push_back("world");
test2.push_back("another");
ret.push_back(test1);
ret.push_back(test2);
return ret;
}
It's the smallest implementation I could think of that usefully exercises the generated interface.
The SWIG interface I wrote provides a skeleton definition of std::vector - just enough to persuade SWIG to actually wrap the thing. We also extend it for the two cases we care about to provide an implementation of __getitem__, the minimum requirement for the obj[x][y] syntax you want to be able to use.
%module Test
%{
#include "test.hh"
%}
namespace std {
template <typename T>
class vector {
};
}
%extend std::vector<std::vector<std::string> > {
std::vector<std::string> __getitem__(unsigned i) throw(std::out_of_range) {
return $self->at(i);
}
}
%extend std::vector<std::string> {
const char * __getitem__(unsigned i) throw(std::out_of_range) {
return $self->at(i).c_str();
}
}
%template (VecString) std::vector<std::string>;
%template (VecVecString) std::vector<std::vector<std::string> >;
%include "test.hh"
There's a trick there with c_str() to avoid including std_string.i. This interface allows me to do things like this in Python:
Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24)
[GCC 4.5.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import Test
>>> t=Test.make()
>>> print t[0][0]
hello
>>>
It currently doesn't raise the correct type of Python exception in __getitem__. You can do that either with %include "exception.i" or with %exception and writing your own try/catch around $action.
You'll probably also want to provide a similar implementation of __setitem__ to make this useful.
This is probably no faster than std_vector.i, or your home brew typemap that converts to Python list of list directly. In general though I don't think doing it like this is a good idea -- using the existing std_vector.i implementation instead of reinventing the wheel seems far more logical.