2014-04-28 12 views
7

Zaczynam rozumieć SWIG, a najnowsza wersja (v3.0) SWIG wydaje się obsługiwać wszystko, czego potrzebuję po wyjęciu z pudełka, w tym C++ 11 funkcje, ale wpadłem w sztylet, jeśli chodzi o używanie shared_ptr z moimi klasami reżyserskimi.Używanie shared_ptr z SWIG Directors dla Java

Udało mi się uzyskać shared_ptr do pracy z normalnymi klasami proxy, ale teraz, w przypadku moich reżyserów, wydaje się, że nie są one wspierane po wyjęciu z pudełka. To daje mi automatycznie wygenerowany typ, taki jak SWIGTYPE_p_std__shared_ptrT_MyDataType_t i generuje zepsuty interfejs, ponieważ nie używa tych samych typów, których używają klasy proxy.

mam uproszczony przykład co usiłuję zrobić (run z swig -c++ -java Test.i na swig 3.0):

Test.i

%module(directors="1") test 
%{ 

%} 

%include <std_shared_ptr.i> 

%shared_ptr(MyDataType) 

class MyDataType { 
public: 
    int value; 
}; 

class NonDirectorClass { 
public: 
    std::shared_ptr<MyDataType> TestMethod(); 
}; 

%feature("director") CallbackBaseClass; 

class CallbackBaseClass { 
public: 
    virtual ~CallbackBaseClass() {}; 
    virtual std::shared_ptr<MyDataType> GetDataFromJava() {}; 
}; 

zasadzie to, co ja zamierzam być jest rozszerzeniem CallbackBaseClass w Javie i chcę móc przekazywać wokół moich zawijanych typów shared_ptr. Klasa non-director generuje typy shared_ptr w sam raz. Pliki proxy dyrektora klasy są generowane poprawnie, ale metody SwigDirector_ w opakowaniu odnoszą się do nieprawidłowych typów.

Wygląda na to, że mogłem ręcznie naprawiać pliki, zmieniając typ SWIGTYPE_p_std__shared_ptrT_MyDataType_t na MyDataType wszędzie, ale mam nadzieję, że ktoś o większej wiedzy na temat słodyczy może odpowiedzieć na pytanie, aby można było wygenerować to poprawnie.

Najlepsza wskazówka, jaką mam, to here, ale nadal próbuję dowiedzieć się, jak poprawnie korzystać z map tego typu, zwłaszcza dla shared_ptr, a nie podstawowych elementów podstawowych.

UPDATE:

Dokumentacja says:

Uwaga: Nie ma jeszcze wsparcia dla% shared_ptr i funkcji dyrektora.

Chociaż nie daje wskazówek, dlaczego. Chciałbym wiedzieć, czy jest to niemożliwe z reżyserami swig, jeśli istnieje dobry powód, dla którego nie należy używać shared_ptr w reżyserach. Wydaje się, że warto używać tych samych typów, których używa się wszędzie indziej. Mam nadzieję, że odpowiedź jest nadal możliwa.

Odpowiedz

5

Najnowsza wersja dokumentacji SWIG teraz brzmi:

„Jest nieco ograniczone wsparcie dla %shared_ptr i funkcja dyrektora i degress sukcesu jest różna w różnych językach docelowych Proszę pomóc poprawić to. wsparcie poprzez dostarczanie poprawek ".

Aby dokonać przykładową pracę wydaje się konieczne dodanie czterech brakujących typemaps, directorin, directorout, javadirectorin i javadirectorout:

%module(directors="1") test 

%include <std_shared_ptr.i> 

%{ 
#include <memory> 
#include <iostream> 
%} 

%shared_ptr(MyDataType) 

%feature("director") CallbackBaseClass; 

%typemap(javadirectorin) std::shared_ptr<MyDataType> "new $typemap(jstype, MyDataType)($1,true)"; 
%typemap(directorin,descriptor="L$typemap(jstype, MyDataType);") std::shared_ptr<MyDataType> %{ 
    *($&1_type*)&j$1 = new $1_type($1); 
%} 

%typemap(javadirectorout) std::shared_ptr<MyDataType> "$typemap(jstype, MyDataType).getCPtr($javacall)"; 
%typemap(directorout) std::shared_ptr<MyDataType> %{ 
    $&1_type tmp = NULL; 
    *($&1_type*)&tmp = *($&1_type*)&$input; 
    if (!tmp) { 
    SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "Attempt to dereference null $1_type"); 
    return NULL; 
    } 
    $result = *tmp; 
%} 

%inline %{ 
class MyDataType { 
public: 
    int value; 
}; 

class NonDirectorClass { 
public: 
    std::shared_ptr<MyDataType> TestMethod() { return std::make_shared<MyDataType>(); } 
}; 

class CallbackBaseClass { 
public: 
    virtual ~CallbackBaseClass() {}; 
    virtual std::shared_ptr<MyDataType> GetDataFromJava() = 0; 
}; 

void frobinate(CallbackBaseClass& cb) { 
    std::cout << "In C++: " << cb.GetDataFromJava()->value << "\n"; 
} 
%} 

Nawet jeśli tylko kiedykolwiek wykorzystać sprawę directorout w próbce directorin typemap jest nadal wymagany, aby wyszukiwanie zakończyło się sukcesem director_connect, ponieważ zależy to od posiadania odpowiedniego deskryptora.

Te cztery mapy typów są identyczne z wersjami, javain i javaout w funkcjonalności, ale zostały odwrócone z powodu ich roli w reżyserach.

Nie są one wystarczająco kompletne, aby obsłużyć wszystkie przypadki, ale działają w twoim przykładzie. Wywołanie $typemap wewnątrz deskryptora wymaga wersji SWIG 3 nowszej niż ta uwzględniona w Ubuntu 14.04 - w formie, w której ją napisałem, jedyna wersja testowana przeze mnie została wyewidencjonowana z pnia. Możesz napisać deskryptor ręcznie (który byłby po prostu descriptor="LMyDataType;"), ale wyraźnie jest to mniej ogólne. Zaletą napisania powyższego jest to, że będzie on poprawnie obsługiwał również dyrektywy %rename. To nie będzie poprawnie obsługiwać pakietów, ale musisz też ręcznie zapisać to w tym przypadku.

udało mi się przetestować i uruchomić przykład, dodałem następujące run.java:

public class run extends CallbackBaseClass { 
    public MyDataType GetDataFromJava() { 
    MyDataType val = new MyDataType(); 
    val.setValue(123); 
    return val; 
    } 

    public static void main(String[] argv) { 
    System.loadLibrary("test"); 
    run r = new run(); 

    System.out.println("In Java: " + r.GetDataFromJava().getValue()); 
    test.frobinate(r); 
    } 
} 

i skompilowane i prowadził go z:

~/swig-trunk/preinst-swig -Wall -c++ -java test.i 
clang++-3.6 -stdlib=libc++ -Wall -Wextra -std=c++1y test_wrap.cxx -o libtest.so -I/usr/lib/jvm/default-java/include/ -I/usr/lib/jvm/default-java/include/linux -shared -fPIC 
javac run.java 
LD_LIBRARY_PATH=. java run 

Które gdy prowadził dał:

In Java: 123 
In C++: 123 

Zgaduję, że w przypadku Javy z shared_ptr + reżyserzy subtelności wokół uzyskania deskryptor jest prawdopodobnie głównym blokerem, który powoduje, że po prostu "działa" po wyjęciu z pudełka.

Powiązane problemy