Use Tcl library with C code gets errors - tcl

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);
}

Related

exposing nonstatic member function of class to chaiscript

I have a project that tries to implement keyboard macro scripting with chaiscript. I am writing a class based on xlib to wrap the xlib code.
I have a member function to add a modifier key to an ignored list, because of a xlib quirk.
how could i do something like the following minimal example.
#include <chaiscript/chaiscript.hpp>
#include <functional>
class MacroEngine{
public:
MacroEngine() = default;
//...
void addIgnoredMod(int modifier){
ignoredMods |= modifier;
}
//...
private:
int ignoredMods;
};
int main(int argc, char *argv[]){
MacroEngine me;
chaiscript::ChaiScript chai;
//...
chai.add(chaiscript::fun(std::bind(&MacroEngine::addIgnoredMod, me, std::placeholders::_1)), "setIgnoredMods");
//...
return 0;
}
I tried bind and failed with the following error message:
In file included from ../deps/ChaiScript/include/chaiscript/dispatchkit/proxy_functions_detail.hpp:24:0,
from ../deps/ChaiScript/include/chaiscript/dispatchkit/proxy_functions.hpp:27,
from ../deps/ChaiScript/include/chaiscript/dispatchkit/proxy_constructors.hpp:14,
from ../deps/ChaiScript/include/chaiscript/dispatchkit/dispatchkit.hpp:34,
from ../deps/ChaiScript/include/chaiscript/chaiscript_basic.hpp:12,
from ../deps/ChaiScript/include/chaiscript/chaiscript.hpp:823,
from ../src/main.cpp:2:
../deps/ChaiScript/include/chaiscript/dispatchkit/callable_traits.hpp: In instantiation of ‘struct chaiscript::dispatch::detail::Callable_Traits<std::_Bind<void (MacroEngine::*(MacroEngine, std::_Placeholder<1>))(unsigned int)> >’:
../deps/ChaiScript/include/chaiscript/language/../dispatchkit/register_function.hpp:45:72: required from ‘chaiscript::Proxy_Function chaiscript::fun(const T&) [with T = std::_Bind<void (MacroEngine::*(MacroEngine, std::_Placeholder<1>))(unsigned int)>; chaiscript::Proxy_Function = std::shared_ptr<chaiscript::dispatch::Proxy_Function_Base>]’
../src/main.cpp:21:95: required from here
../deps/ChaiScript/include/chaiscript/dispatchkit/callable_traits.hpp:99:84: error: decltype cannot resolve address of overloaded function
typedef typename Function_Signature<decltype(&T::operator())>::Signature Signature;
^~~~~~~~~
../deps/ChaiScript/include/chaiscript/dispatchkit/callable_traits.hpp:100:86: error: decltype cannot resolve address of overloaded function
typedef typename Function_Signature<decltype(&T::operator())>::Return_Type Return_Type;
^~~~~~~~~~~
I also tried to make the variable static which worked, but it wont work if I try to make it possible to ignore modifiers on a per hotkey basis.
what am i doing wrong? and how can I fix it?
You can do this instead:
chai.add(chaiscript::fun(&MacroEngine::addIgnoredMod, &me), "addIgnoredMod");
Or use a lambda:
chai.add(chaiscript::fun([&me](int modifier){ me.addIgnoredMod(modifier); }), "addIgnoredMod");
Jason Turner, the creator of Chaiscript, commented on it here: http://discourse.chaiscript.com/t/may-i-use-std-bind/244/4
"There’s really never any good reason to use std::bind. I much better solution is to use a lambda (and by much better, I mean much much better. std::bind adds to compile size, compile time and runtime)."

Return a c array from a code, wrapped by cython, to python,

I am trying to run my C++ code from python, since I want to couple it with an open source software which has python interface, so I used cython for the sake of wrapping . My C++ code can be compiled from python but I have some problems in returning the results which are float vectors. I can return a single float or integer to python but not a vector. I tried to return the pointer, like what is normally done for C++ functions, but python does not recognize the pointer form C++.
here is a simplified code to show what do I mean.
my .hpp file is:
#include "mpi.h"
float my_cppfun(int D);
my .cpp file:
#include <stdio.h>
#include <stdlib.h>
#include <vector>
#include "my_cpp.hpp"
float my_cppfun(int D)
{
float DD[D];
int i;
for (i=0;i<D;i++){
DD[i]=i;
}
return DD[i-1];
//return DD instead of DD[i-1]
}
my .pyx file is:
cdef extern from "my_cpp.hpp":
float my_cppfun(int)
def my_cpp(int D):
return my_cppfun(D)
my .py file is:
from mpi4py import MPI
from pympi import my_cpp
y=my_cpp(3)
print y
There is also setup.py file and it is working at the moment. I am wondering how can I return DD array instead of single float value(DD[i-1]).
Thanks in advance for your help.
You are going to need to make a list and return that.
The documentation for List should help. PyList_New, PyList_SetItem, etc.

Preprocessor for_each witin SWIG interface

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.

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.

Cython: call function from external C file

After Cython's "Hello World" and the example of calling a function in the C math libraries here, what I really want to do is to have C code of my own in a separate file and use it from Cython. Following this, I modify the setup.py file:
sourcefiles = ['hello2_caller.pyx', 'hello2.c']
This is hello2.c (main is just there to compile and test it separately---though that product isn't present for the test:
#import <stdio.h>
void f() {
printf("%s", "Hello world!\n");
}
int main(int argc, const char* argv[]) {
f();
return 0;
}
This is hello2_caller.pyx
cdef extern from "hello2.c":
void f()
cpdef myf():
f()
I get:
In file included from hello2_caller.c:219:
hello2.c:3: warning: function declaration isn’t a prototype
So I guess I'm failing to provide a header in some way.. though just feeding setup.py a standard header like 'hello2.h' doesn't work. Can you point me to a working example or explain what I'm doing wrong. Thanks.
Thanks to help from the Cython users' list here.
My writeup here.
Bottom line: this is only a warning, that is not fixed by a declaration of f(), but the compiled .so works. I'm still not sure how you would provide a .h file to Cython or if there is a better way to do this.
And there's a couple of errors: should be #include, and don't list the .c file in sourcfiles.