L'approccio migliore che ho trovato è stato quello di scrivere il mio typemap. Speravo in alcune semplici istruzioni SWIG.
Nel caso qualcuno altro ha bisogno questo, ecco come ho fatto. Tieni presente che non sono un esperto SWIG.
In primo luogo, è necessario definire alcuni typemaps da applicare a std :: string & argomenti. Devi solo definirli una volta. (Nota:. Ci sono typemaps aggiuntivi che possono essere richiesti in alcune configurazioni)
modello argomento
%typemap(jni) std::string *INOUT, std::string &INOUT %{jobjectArray%}
%typemap(jtype) std::string *INOUT, std::string &INOUT "java.lang.String[]"
%typemap(jstype) std::string *INOUT, std::string &INOUT "java.lang.String[]"
%typemap(javain) std::string *INOUT, std::string &INOUT "$javainput"
%typemap(in) std::string *INOUT (std::string strTemp), std::string &INOUT (std::string strTemp) {
if (!$input) {
SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "array null");
return $null;
}
if (JCALL1(GetArrayLength, jenv, $input) == 0) {
SWIG_JavaThrowException(jenv, SWIG_JavaIndexOutOfBoundsException, "Array must contain at least 1 element");
return $null;
}
jobject oInput = JCALL2(GetObjectArrayElement, jenv, $input, 0);
if (NULL != oInput) {
jstring sInput = static_cast<jstring>(oInput);
const char * $1_pstr = (const char *)jenv->GetStringUTFChars(sInput, 0);
if (!$1_pstr) return $null;
strTemp.assign($1_pstr);
jenv->ReleaseStringUTFChars(sInput, $1_pstr);
}
$1 = &strTemp;
}
%typemap(freearg) std::string *INOUT, std::string &INOUT ""
%typemap(argout) std::string *INOUT, std::string &INOUT
{
jstring jStrTemp = jenv->NewStringUTF(strTemp$argnum.c_str());
JCALL3(SetObjectArrayElement, jenv, $input, 0, jStrTemp);
}
successivo, per ogni C++ come questo ...
void foo(std::string & xyzzy);
void bar(std::string & xyzzy);
void baz(..., std::string & xyzzy, ...);
... si applica la typemaps sopra con questa direttiva SWIG:
%apply std::string &INOUT { std::string & xyzzy };
Gli attacchi risultanti simile a questa:
public void foo(java.lang.String[] xyzzy);
public void bar(java.lang.String[] xyzzy);
public void baz(..., java.lang.String[] xyzzy, ...);
essi necessitano di un elemento dell'array String. All'ingresso, il primo elemento potrebbe essere nullo. Se non null, viene convertito in un valore di stringa std :: 8 UTF e passato alla funzione C++. All'uscita, il valore della stringa std :: passata per riferimento viene convertito da UTF-8 in una stringa Java.
Perché la classe String di Java è immutabile. Quindi, anche se passi una matrice falsa di String, non puoi modificarla come stai implicando passando un riferimento. –
@Martin York - Gli oggetti stringa sono immutabili. I membri di un array String, tuttavia, sono riferimenti mutabili agli oggetti String. –
@Andy Thomas-Cramer: Ma non è come passare per riferimento. Stai passando un oggetto che puoi manipolare. Ma con una serie di stringhe l'oggetto non è ancora modificabile. A meno che tu non stia suggerendo che la funzione chiamata può cambiare la stringa sostituendola! Quale richiederebbe quindi il codice Glue per prendere l'oggetto stringa Java restituito e inserirlo nell'oggetto stringa C++ passato. –