2013-02-28 2 views
2

Учитывая C методы ++ какC# SWIG вектор <string> в строку []

std::vector<std::string> getFoo(); 
void setFoo(const std::vector<std::string> &foo); 

Как я могу получить SWIG, чтобы выставить его, как это C#

string[] getFoo(); 
setFoo(string[] foo); 

Я понимаю, что многие из people have asked о vector<string> и SWIG, но я ничего не видел, обращаясь к конверсии в/из string[]. Каждый упоминает, используя шаблоны Swig, как этого

%template(StringVector) vector<string>; 

Но это только создает тип данных, который абоненты должны знать маршал вручную. В идеале, вызывающий абонент должен будет иметь дело только с string[], и пусть слой SWIG выберет его.

Как я могу просто использовать string[] в C#, но он превращается в vector<string> в C++?

ответ

2

Один из подходов может заключаться в том, чтобы добавить implicit casting в SWIG-сгенерированный StringVector, чтобы он мог использовать себя/от string[].

Я пробовал делать это через typemap, но не смог заставить его работать. Однако это можно сделать с помощью partial classes.

Это выглядит примерно так. В SWIG,

%include std_vector.i 
%include std_string.i 

/* allow partial c# classes */ 
%typemap(csclassmodifiers) SWIGTYPE "public partial class" 

/* generate template around vector<string> */ 
%template(StringVector) std::vector<std::string>; 

Затем в C#, создать частичную версию StringVector:

public partial class StringVector: IDisposable, System.Collections.IEnumerable 
#if !SWIG_DOTNET_1 
    , System.Collections.Generic.IList<string> 
#endif 
{ 
    // cast from C# string array 
    public static implicit operator StringVector(string[] inVal) { 
     var outVal= new StringVector(); 
     foreach (string element in inVal) { 
      outVal.Add(element); 
     } 
     return outVal; 
    } 

    // cast to C# string array 
    public static implicit operator string[](StringVector inVal) { 
     var outVal= new string[inVal.Count]; 
     inVal.CopyTo(outVal); 
     return outVal; 
    } 
} 

Это позволяет писать C# код, который выглядит следующим образом:

string[] foo= mymodule.getFoo(); 
string[] thenewfoo= { "one", "two", "three" }; 
mymodule.setFoo(thenewfoo); 

Это еще StringVector в сигнатурах метода C#, но так как клиентский кодер может просто использовать string[], это не имеет большого значения.

+0

Я чувствую, что это приносит в жертву немалую эффективность ради совместимости интерфейса. Опять же, я, вероятно, придумаю такую ​​же идею. +1 – sehe

+0

Я полагаю, что большинство людей, использующих интерфейс SWIG, действительно захотят 'string []', поэтому они все равно будут преобразовывать его вручную. Во всяком случае, одним из преимуществ этого подхода является то, что вы * можете * использовать StringVector напрямую, если бы эффективность имела значение. – paleozogt

+0

Также обратите внимание, что это действительно будет работать только с compiletime. Вы не можете передать StringVector в какой-либо общий метод и все еще ожидаете, что он выполнит преобразование, определяемое пользователем (для этого нет ограничений типа generic). Хотя, C# 4.0 ''dynamic' мог бы его отключить (нужно проверить). – sehe

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