Класс std :: ostream требует для вывода объект std :: streambuf. Это используется классами fstream и stringstream, которые используют функции ostream, предоставляя пользовательскую реализацию класса streambuf.
Таким образом, вы можете написать свою собственную реализацию std :: streambuf с перезаписанным методом переполнения, буферизуя входящие символы во внутренний строковый буфер. Каждый вызов x или eof / newline генерирует строку java и вызывает метод print вашего java PrintStream.
Неполный пример класса:
class JavaStreamBuff : std::streambuf
{
std::stringstream buff;
int size;
jobject handle;
JNIEnv* env
//Ctor takes env pointer for the working thread and java.io.PrintStream
JavaStreamBuff(JNIEnv* env, jobject jobject printStream, int buffsize = 50)
{
handle = env->NewGlobalRef(printStream);
this->env = env;
this->size = size;
}
//This method is the central output of the streambuf class, every charakter goes here
int overflow(int in)
{
if(in == eof || buff.size() == size)
{
std::string blub = buff.str();
jstring do = //magic here, convert form current locale unicode then to java string
jMethodId id = env->(env->GetObjectClass(handle),"print","(java.lang.String)V");
env->callVoidMethod(id,handle,do);
buff.str("");
}
else
{buff<<in;}
}
virtual ~JavaStreamBuff()
{
env->DeleteGlobalRef(handle);
}
}
Отсутствует:
Поддержка многопоточности (указатель env действителен только для потока jvm)
Обработка ошибок (проверка на наличие исключений Java)
Тестирование (записано за последние 70 минут)
Собственный метод Java для установки потока печати.
На стороне java вам нужен класс для преобразования PrintStream в BufferedReader.
Там должны быть некоторые ошибки, не тратить достаточно времени на их работу.
Класс требует, чтобы весь доступ был из потока, в котором он был создан.
Надеюсь, это поможет
Примечание
Я получил его для работы с Visual Studio, но я не могу заставить его работать с g ++, попробую отладить это позже.
Редактировать
Похоже, мне следовало бы поискать более официальный учебник по этому поводу, публикуя мой ответ, на странице MSDN по этой теме получен строковый буфер другим способом.
Извините за публикацию без проверки лучше: - (.
Небольшое исправление приведенного выше кода в более или менее не связанной точке: просто реализуйте InputStream с помощью пользовательского класса и вставьте массивы byte [] вместо Strings из c ++.
InputStream имеет небольшой интерфейс, и BufferedReader должен выполнять большую часть работы.
Последнее обновление, так как я не могу заставить его работать на linux, даже с комментариями к классу std :: streambuf, в которых говорится, что только переполнение должно быть перезаписано.
Эта реализация помещает необработанные строки во входной поток, который может быть прочитан другим потоком. Так как я слишком глуп, чтобы заставить отладчик работать не проверенным, снова.
//The c++ class
class JavaStreamBuf :public std::streambuf
{
std::vector<char> buff;
unsigned int size;
jobject handle;
JNIEnv* env;
public:
//Ctor takes env pointer for the working thread and java.io.PrintStream
JavaStreamBuf(JNIEnv* env, jobject cppstream, unsigned int buffsize = 50)
{
handle = env->NewGlobalRef(cppstream);
this->env = env;
this->size = size;
this->setbuf(0,0);
}
//This method is the central output of the streambuf class, every charakter goes here
virtual int_type overflow(int_type in = traits_type::eof()){
if(in == std::ios::traits_type::eof() || buff.size() == size)
{
this->std::streambuf::overflow(in);
if(in != EOF)
buff.push_back(in);
jbyteArray o = env->NewByteArray(buff.size());
env->SetByteArrayRegion(o,0,buff.size(),(jbyte*)&buff[0]);
jmethodID id = env->GetMethodID(env->GetObjectClass(handle),"push","([B)V");
env->CallVoidMethod(handle,id,o);
if(in == EOF)
env->CallVoidMethod(handle,id,NULL);
buff.clear();
}
else
{
buff.push_back(in);
}
return in;
}
virtual ~JavaStreamBuf()
{
overflow();
env->DeleteGlobalRef(handle);
}
//The java class
/**
*
*/
package jx;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author josefx
*
*/
public class CPPStream extends InputStream {
List<Byte> data = new ArrayList<Byte>();
int off = 0;
private boolean endflag = false;
public void push(byte[] d)
{
synchronized(data)
{
if(d == null)
{
this.endflag = true;
}
else
{
for(int i = 0; i < d.length;++i)
{
data.add(d[i]);
}
}
}
}
@Override
public int read() throws IOException
{
synchronized(data)
{
while(data.isEmpty()&&!endflag)
{
try {
data.wait();
} catch (InterruptedException e) {
throw new InterruptedIOException();
}
}
}
if(endflag)return -1;
else return data.remove(0);
}
}
Извините, что потратил столько места ^^ (и время: - ().