Я хочу вернуть список указателей от C++ до Tcl. Затем вызовите некоторые функции-члены указателями. SWIG может помочь мне в этом.Swig: Как вернуть список указателей от C++ до Tcl
Однако, SWIG дайте мне список указатель на указатель.
% getLongTime 10
_30a8620000000000_p_p_MyData _30bc620000000000_p_p_MyData
Я не могу найти синтаксис для разыменования в SWIG. Поэтому мне приходится писать функции разыменования для каждого класса. Это очень неудобно.
Включая «std_vector.i», чтобы вернуть список указателей. У кого-нибудь есть пример, который использует вектор, но без второго указателя? Или любое альтернативное решение в порядке!
Я также попытался написать общую функцию разыменования, как:
void * dereference(void ** p){ return *p; }
Однако, это не работает. Tcl дает мне ошибку типа:
TypeError in method 'dereference', argument 1 of type 'void **
Я упростил код, если вы хотите попробовать свою программу. Вот мой main.cpp:
#include <cstdlib>
#include <vector>
using namespace std;
#include "main.hh"
#include <tcl.h>
std::vector<MyData> MyData::AllTime; // It seems the place of this statement matters
std::vector<MyData*> getLongTime(int limit) {
vector<MyData*> longTime;
for(int i = 0; i <= 3; ++i)
if (MyData::AllTime[i].getMinute() >= limit)
longTime.push_back(&MyData::AllTime[i]);
return longTime;
}
MyData* derefMyData(MyData** p) {return *p;} // I have to write a dereference function for every class
/// print command, exectue it and print resulte
void print(Tcl_Interp *interp, const char *command) {
printf("%% %s\n", command);
Tcl_Eval(interp, command);
const char *msg = Tcl_GetStringResult(interp);
if (*msg != '\0')
printf("%s\n", msg);
}
int main(int argc, char** argv) {
Tcl_Interp *interp = Tcl_CreateInterp();
Tcl_Eval(interp, "load ./swig.so swig");
MyData::AllTime.push_back(MyData(10));
MyData::AllTime.push_back(MyData(15));
MyData::AllTime.push_back(MyData(9));
// set the time exceeding 10 to 10 by tcl function.
print(interp, "set times [getLongTime 10]");
print(interp, "foreach t $times { [derefMyData $t] setMinute 10}");
printf("All times:");
for(std::vector<MyData>::iterator i = MyData::AllTime.begin(); i != MyData::AllTime.end(); ++i)
printf("%d ", i->getMinute());
printf("\n");
Tcl_DeleteInterp(interp);
return 0;
}
Вот мой main.hh
#ifndef MAIN_HH
#define MAIN_HH
#include <cstdlib>
#include <stdio.h>
#include <vector>
using namespace std;
class MyData{
int minute;
public:
MyData(int minute):minute(minute){};
int getMinute(){return minute;};
void setMinute(int m){ minute = m; };
static std::vector<MyData> AllTime;
};
std::vector<MyData*> getLongTime(int limit);
MyData* derefMyData(MyData** p);
#endif /* MAIN_HH */
Вот мой swig.i
/* swig.i */
%module swig
%{
#include "main.hh"
%}
%include "std_vector.i"
namespace std {
%template(myDataVector) std::vector<MyData *>;
}
class MyData{
public:
MyData(int minute);
void setMinute(int m);
};
extern std::vector<MyData*> getLongTime(int limit);
extern MyData* derefMyData(MyData** p);
Вот команды мой компиляции
swig -c++ -tcl swig.i
g++ -fpic -c main.cpp swig_wrap.cxx
g++ -shared main.o swig_wrap.o -o swig.so ;# I don't need to compile with main.o in my original program.
g++ main.o -o swig.out -g -I/usr/local/include -L/usr/local/lib -ltcl8.5
setenv LD_LIBRARY_PATH /usr/local/lib:/usr/local/lib
./swig.out
И вот вывод:
% set times [getLongTime 10]
_30a8620000000000_p_p_MyData _80bb620000000000_p_p_MyData
% foreach t $times { [derefMyData $t] setMinute 10}
All times:10 10 9
Кстати, упрощенный отчет программы * Glibc обнаружен *
Я не знаю, как это исправить.
К счастью, моя оригинальная программа в порядке.
Если кто-нибудь знает, как это исправить. Пожалуйста, дайте мне знать.
Моя версия SWIG: 1.3.29
Моя НКУ версия: 4.5.2
Правильно говоря, вы должны вызывать 'Tcl_FindExecutable (argv [0]);' от 'main' перед выполнением' Tcl_CreateInterp', поскольку это инициализирует библиотеку Tcl, хотя я не думаю, что это исправит для вас , –