2016-05-10 1 views
2

Я хочу вернуть список указателей от 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

+0

Правильно говоря, вы должны вызывать 'Tcl_FindExecutable (argv [0]);' от 'main' перед выполнением' Tcl_CreateInterp', поскольку это инициализирует библиотеку Tcl, хотя я не думаю, что это исправит для вас , –

ответ

0

Я думаю, что проблема в том, что вы не получили SWIG TypeMap для MyData *, а просто для MyData (или, возможно, &MyData; мой C++ немного шаткий). Это делает SWIG генерировать код, который не делает то, что вы ожидаете; _30a8620000000000_p_p_MyData является дескриптором ячейки в значении, скопированном из локальной переменной longTime, и поэтому отображаемый тип дескриптора является указателем на содержимое ячеек, то есть MyData **.

Вы можете получить лучшие результаты, если вы вернете const vector<MyData *>. Это, несомненно, будет иметь больше смысла на стороне Tcl, где сами ценности фактически постоянны. Я не знаю, достаточно ли SWIG, чтобы воспользоваться этим. Возможно, вам придется самостоятельно написать код карты (это разумно, если ваш реальный код намного длиннее этого).

 Смежные вопросы

  • Нет связанных вопросов^_^