I am translating a java class to C#, however, I am unsure that I have done it properly. In my code below, RewardRequestListener's OnFinishedEvent should be called, however, it never hits a breakpoint or logs anything.
Here is my Java:
private RequestListener<Resource> mRequestListener = new RequestListener<Resource>() {
#Override
public void onFinished(Kiip manager, Resource response) {
if (response != null) {
if (mRewardActionToggle.isChecked()) {
manager.showResource(response);
} else {
toast("Reward Queued");
mResources.add(response);
}
} else {
toast("No Reward");
}
}
#Override
public void onError(Kiip manager, KiipException error) {
toast("error (" + error.getCode() + ") " + error.getMessage());
}
};
Here is my C#:
private static readonly string TAG = "example";
private Button mUnlockAchievement, mSaveLeaderboard, mShowNotification, mShowFullscreen, mGetActivePromos, mNewActivity;
private EditText mAchievementId, mLeaderboardId;
private static ToggleButton mPositionToggle, mRewardActionToggle;
private List<ME.Kiip.Api.Resource> mResources = new List<ME.Kiip.Api.Resource>();
private RewardRequestListener mRewardsListener;
private ActivePromosRequestListener mActivePromosListener;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
mRewardsListener = new RewardRequestListener(this);
}
class RewardRequestListener : Kiip.IRequestListener
{
ExampleActivity example = new ExampleActivity();
public RewardRequestListener(ExampleActivity example)
{
this.example = example;
}
public void OnError(Kiip p0, KiipException p1)
{
example.toast("error (" + p1.Code + ") " + p1.Message);
}
public void OnFinished(Kiip p0, Java.Lang.Object p1)
{
ME.Kiip.Api.Resource response = p1 as ME.Kiip.Api.Resource;
if (response != null)
{
if (mRewardActionToggle.Checked)
{
p0.ShowResource(response);
}
else
{
example.mResources.Add(response);
}
}
else
{
example.toast("No Reward");
}
}
public IntPtr Handle { get; set; }
public void Dispose()
{
}
}
public void OnClick(View v)
{
Kiip manager = Kiip.Instance;
switch (v.Id)
{
case Resource.Id.unlockAchievement:
manager.UnlockAchievement(mAchievementId.Text, mRewardsListener);
break;
}
}
Related
This is the script.. in the starting lines you can see the usage of keycodes. I want to add UI buttons for android. When the user tap on that button it acts as Keycode.A or any Keycode which I want and I don't want to change the script. Any solution ? I am totally beginner I don't understand much of this code so don't want to change it. I got it with the free asset 2D Game Kit in which character ellen moves with pc controls. All I want is to change character controls from pc to ui buttons. Please help if I have to change the script I will get a lot of errors which I can't handle so please help.
using UnityEngine;
using UnityEngine.UIElements;
namespace Gamekit2D
{
public class PlayerInput : InputComponent, IDataPersister
{
public static PlayerInput Instance
{
get { return s_Instance; }
}
protected static PlayerInput s_Instance;
public bool HaveControl { get { return m_HaveControl; } }
public InputButton Pause = new InputButton(KeyCode.Escape, XboxControllerButtons.Menu);
public InputButton Interact = new InputButton(KeyCode.E, XboxControllerButtons.Y);
public InputButton MeleeAttack = new InputButton(KeyCode.K, XboxControllerButtons.X);
public InputButton RangedAttack = new InputButton(KeyCode.O, XboxControllerButtons.B);
public InputButton Jump = new InputButton(KeyCode.Space, XboxControllerButtons.A);
public InputAxis Horizontal = new InputAxis(KeyCode.D, KeyCode.A, XboxControllerAxes.LeftstickHorizontal);
public InputAxis Vertical = new InputAxis(KeyCode.W, KeyCode.S, XboxControllerAxes.LeftstickVertical);
[HideInInspector]
public DataSettings dataSettings;
protected bool m_HaveControl = true;
protected bool m_DebugMenuIsOpen = false;
void Awake ()
{
if (s_Instance == null)
s_Instance = this;
else
throw new UnityException("There cannot be more than one PlayerInput script. The instances are " + s_Instance.name + " and " + name + ".");
}
void OnEnable()
{
if (s_Instance == null)
s_Instance = this;
else if(s_Instance != this)
throw new UnityException("There cannot be more than one PlayerInput script. The instances are " + s_Instance.name + " and " + name + ".");
PersistentDataManager.RegisterPersister(this);
}
void OnDisable()
{
PersistentDataManager.UnregisterPersister(this);
s_Instance = null;
}
protected override void GetInputs(bool fixedUpdateHappened)
{
Pause.Get(fixedUpdateHappened, inputType);
Interact.Get(fixedUpdateHappened, inputType);
MeleeAttack.Get(fixedUpdateHappened, inputType);
RangedAttack.Get(fixedUpdateHappened, inputType);
Jump.Get(fixedUpdateHappened, inputType);
Horizontal.Get(inputType);
Vertical.Get(inputType);
if (Input.GetKeyDown(KeyCode.F12))
{
m_DebugMenuIsOpen = !m_DebugMenuIsOpen;
}
}
public override void GainControl()
{
m_HaveControl = true;
GainControl(Pause);
GainControl(Interact);
GainControl(MeleeAttack);
GainControl(RangedAttack);
GainControl(Jump);
GainControl(Horizontal);
GainControl(Vertical);
}
public override void ReleaseControl(bool resetValues = true)
{
m_HaveControl = false;
ReleaseControl(Pause, resetValues);
ReleaseControl(Interact, resetValues);
ReleaseControl(MeleeAttack, resetValues);
ReleaseControl(RangedAttack, resetValues);
ReleaseControl(Jump, resetValues);
ReleaseControl(Horizontal, resetValues);
ReleaseControl(Vertical, resetValues);
}
public void DisableMeleeAttacking()
{
MeleeAttack.Disable();
}
public void EnableMeleeAttacking()
{
MeleeAttack.Enable();
}
public void DisableRangedAttacking()
{
RangedAttack.Disable();
}
public void EnableRangedAttacking()
{
RangedAttack.Enable();
}
public DataSettings GetDataSettings()
{
return dataSettings;
}
public void SetDataSettings(string dataTag, DataSettings.PersistenceType persistenceType)
{
dataSettings.dataTag = dataTag;
dataSettings.persistenceType = persistenceType;
}
public Data SaveData()
{
return new Data<bool, bool>(MeleeAttack.Enabled, RangedAttack.Enabled);
}
public void LoadData(Data data)
{
Data<bool, bool> playerInputData = (Data<bool, bool>)data;
if (playerInputData.value0)
MeleeAttack.Enable();
else
MeleeAttack.Disable();
if (playerInputData.value1)
RangedAttack.Enable();
else
RangedAttack.Disable();
}
void OnGUI()
{
if (m_DebugMenuIsOpen)
{
const float height = 100;
GUILayout.BeginArea(new Rect(30, Screen.height - height, 200, height));
GUILayout.BeginVertical("box");
GUILayout.Label("Press F12 to close");
bool meleeAttackEnabled = GUILayout.Toggle(MeleeAttack.Enabled, "Enable Melee Attack");
bool rangeAttackEnabled = GUILayout.Toggle(RangedAttack.Enabled, "Enable Range Attack");
if (meleeAttackEnabled != MeleeAttack.Enabled)
{
if (meleeAttackEnabled)
MeleeAttack.Enable();
else
MeleeAttack.Disable();
}
if (rangeAttackEnabled != RangedAttack.Enabled)
{
if (rangeAttackEnabled)
RangedAttack.Enable();
else
RangedAttack.Disable();
}
GUILayout.EndVertical();
GUILayout.EndArea();
}
}
}
}
It's not possible. I rather advice you to directly call the functions you want when the button is pressed.
Guys
I've implemented into my Unity project a plugin which can be downloaded at the link (https://github.com/HoseinPorazar/Android-Native-TTS-plugin-for-Unity-3d).
To use it you need:
1-import AndroidNativeTTS.unitypackage into your project
2-create an empty game object and rename it to tts.
3-attach test script and TextToSpeech script to tts game object.
4-add a button and set the on click event to test.Speak().
5-build project for Android platform.
After implementing the plugin to make it work it's necessary to delete in AndroidManifext.xml the line "android:label=NAtive TTS".
AndroidManifest.xml is stored in the directory "Assets\Plugin\Android\androidtts-release.aar"
When I implemented the plugin which is build to use "UK" and "US" locale, I tried to add Russian locale but unfortunately it failed.
Please see the scripts below (Test.cs and TextToSpeach.cs):
test.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class test : MonoBehaviour {
TextToSpeech tts;
void Start()
{
tts = GetComponent<TextToSpeech>();
}
public void Speak()
{
tts.Speak("hello mr hosein porazar kasin", (string msg) =>
{
tts.ShowToast(msg);
});
}
public void ChangeSpeed()
{
tts.SetSpeed(0.5f);
}
public void ChangeLanguage()
{
tts.SetLanguage(TextToSpeech.Locale.UK);
}
public void ChangePitch()
{
tts.SetPitch(0.6f);
}
}
TextToSpeech.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TextToSpeech :MonoBehaviour
{
void Start()
{
}
public enum Locale
{
UK = 0,
US = 1
}
private AndroidJavaObject TTSExample = null;
private AndroidJavaObject activityContext = null;
private Locale _lang;
public Locale Language { get { return _lang; } set { SetLanguage(value); } }
private float _pitch, _speed;
public float Pitch { get{return _pitch;} set { SetPitch(value); } }
public float Speed { get{return _speed;} set { SetSpeed(value); } }
public delegate void OnErrorCallbackHandler(string error);
private OnErrorCallbackHandler _callback;
public TextToSpeech()
{
//Initialize();
}
public TextToSpeech(Locale language)
{
Initialize();
this.Language = language;
SetLanguage(this.Language);
}
public TextToSpeech(Locale language,float speed,float pitch)
{
Initialize();
this.Language = language;
this.Pitch = pitch;
this.Speed = speed;
SetLanguage(this.Language);
SetSpeed(this.Speed);
SetPitch(this.Pitch);
}
public void Speak(string toSay,OnErrorCallbackHandler callback)
{
if (TTSExample == null)
{
Initialize();
}
this._callback = callback;
TTSExample.Call("TTSMEWithCallBack", toSay, gameObject.name, "OnError");
}
public void OnError(string error)
{
if (_callback != null)
{
if (error.Length > 0)
{
_callback.Invoke(error);
}
}
ShowToast(error);
}
public void Speak(string toSay)
{
if (TTSExample == null)
{
Initialize();
}
TTSExample.Call("TTSME", toSay);
}
public void SetLanguage(Locale lan)
{
this._lang = lan;
string[] Language = new string[] {"UK","US" };
if (TTSExample == null)
{
Initialize();
}
TTSExample.Call("SetLang", Language[(int)lan]);
}
public void SetSpeed(float speed)
{
this._speed = speed;
if (TTSExample == null)
{
Initialize();
}
TTSExample.Set<float>("Speed", speed);
}
public void SetPitch(float pitch)
{
this._pitch = pitch;
if (TTSExample == null)
{
Initialize();
}
TTSExample.Set<float>("Pitch", pitch);
}
private void Initialize()
{
if (TTSExample == null)
{
using (AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
activityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");
}
using (AndroidJavaClass pluginClass = new AndroidJavaClass("ir.hoseinporazar.androidtts.TTS"))
{
if (pluginClass != null)
{
TTSExample = pluginClass.CallStatic<AndroidJavaObject>("instance");
TTSExample.Call("setContext", activityContext);
}
}
}
}
public void ShowToast(string msg)
{
if (TTSExample == null)
{
using (AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
{
activityContext = activityClass.GetStatic<AndroidJavaObject>("currentActivity");
}
using (AndroidJavaClass pluginClass = new AndroidJavaClass("ir.hoseinporazar.androidtts.TTS"))
{
if (pluginClass != null)
{
TTSExample = pluginClass.CallStatic<AndroidJavaObject>("instance");
TTSExample.Call("setContext", activityContext);
activityContext.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
TTSExample.Call("showMessage", msg);
}));
}
}
}
else
{
activityContext.Call("runOnUiThread", new AndroidJavaRunnable(() =>
{
TTSExample.Call("showMessage", msg);
}));
}
}
}
I've tried to format following lines to change the language to Russian but it didn't help me:
public enum Locale
{
RU = 0,
US = 1
}
public void SetLanguage(Locale lan)
{
this._lang = lan;
string[] Language = new string[] {"RU","US" };
if (TTSExample == null)
{
Initialize();
}
TTSExample.Call("SetLang", Language[(int)lan]);
}
I also tried to contatct the developer of the plugin but it seems he was last time on github a couple years ago.
I'd really appreciate it if somebody can help me with the issue.
On the plugin homepage, the author says...
I have included 2 languages (UK,and US) if you want to use other
languages you will have to modify plugin ( with Android Studio).
So it seems you will also need to change switch statement at the bottom of the Java code here:
https://github.com/HoseinPorazar/Android-Native-TTS-plugin-for-Unity-3d/blob/master/NativeAndroidTTS/androidtts/src/main/java/ir/hoseinporazar/androidtts/TTS.java
By adding an "RU" case like this...
public void SetLang(String loc){
switch (loc){
case "UK":
if(t1!=null)
t1.setLanguage(Locale.UK);
break;
case "US":
if(t1!=null)
t1.setLanguage(Locale.US);
break;
case "RU":
if(t1!=null)
t1.setLanguage(Locale.RU);
break;
}
}
Im using google play services cloud save. I found a tutorial about how to save, but for one thing like just for highscore. I want to save multiple playerprefs, for example I have 3 ability and every one of it is saving in a playerpref so I want to save them in to the cloud and I have gold to buy these abilitys and you can buy the gold with IAP so I want to save gold too in cloud but I have no idea how to save multiple playerprefs can you help me.
My playerprefs is like this
PlayerPrefs.SetInt("Revive", revive);
PlayerPrefs.SetInt("SlowTime", slowTime);
PlayerPrefs.SetInt("Immortal", immortal);
Im changing and saving the gold after IAP purchase
PlayerPrefs.SetInt("Gold", PlayerPrefs.GetInt("Gold") + 250);
This is the Cloud Save Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GooglePlayGames;
using UnityEngine.SocialPlatforms;
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.SavedGame;
using System.Text;
using System;
public class PlayGamesController : MonoBehaviour
{
public static PlayGamesController Instance { set; get; }
const string Save_Name = "Save";
bool isSaving;
bool isCloudDataLoaded = false;
private void Start()
{
if (Instance == null)
{
DontDestroyOnLoad(gameObject);
Instance = this;
}
else
{
Destroy(gameObject);
}
if (!PlayerPrefs.HasKey(Save_Name))
PlayerPrefs.SetString(Save_Name, "0");
if (!PlayerPrefs.HasKey("IsFirstTime"))
PlayerPrefs.SetInt("IsFirstTime", 1);
LoadLocal();
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder().EnableSavedGames().Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.Activate();
SignIn();
}
private void SignIn()
{
Social.localUser.Authenticate((success) => {
LoadData();
});
}
public void AddScoreToLeaderboard(string leaderboardId, long score)
{
Social.ReportScore(score, leaderboardId, (bool success) => { });
}
public void OnAchievementClick()
{
if (Social.localUser.authenticated)
{
Social.ShowAchievementsUI();
}
if (!Social.localUser.authenticated)
{
SignIn();
}
}
public void OnLeaderboardClick()
{
if (Social.localUser.authenticated)
{
Social.ShowLeaderboardUI();
}
if (!Social.localUser.authenticated)
{
SignIn();
}
}
#region Saved Games
string GameDataToString()
{
return CloudVariables.highScore.ToString();
}
void StringToGameData(string cloudData, string localData)
{
if(PlayerPrefs.GetInt("IsFirstTime") == 1)
{
PlayerPrefs.SetInt("IsFirstTime", 0);
if (int.Parse(cloudData) > int.Parse(localData))
{
PlayerPrefs.SetString(Save_Name, cloudData);
}
}
else
{
if(int.Parse(localData) > int.Parse(cloudData))
{
CloudVariables.highScore = int.Parse(localData);
AddScoreToLeaderboard(GPGSIds.leaderboard_high_score, CloudVariables.highScore);
isCloudDataLoaded = true;
SaveData();
return;
}
}
CloudVariables.highScore = int.Parse(cloudData);
isCloudDataLoaded = true;
}
void StringToGameData(string localData)
{
CloudVariables.highScore = int.Parse(localData);
}
public void LoadData()
{
if (Social.localUser.authenticated)
{
isSaving = false;
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithManualConflictResolution(Save_Name, DataSource.ReadCacheOrNetwork, true, ResolveConflict, OnSavedGameOpened);
}
else
{
LoadLocal();
}
}
private void LoadLocal()
{
StringToGameData(PlayerPrefs.GetString(Save_Name));
}
public void SaveData()
{
if (!isCloudDataLoaded)
{
SaveLocal();
return;
}
if (Social.localUser.authenticated)
{
isSaving = true;
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithManualConflictResolution(Save_Name, DataSource.ReadCacheOrNetwork, true, ResolveConflict, OnSavedGameOpened);
}
else
{
SaveLocal();
}
}
private void SaveLocal()
{
PlayerPrefs.SetString(Save_Name, GameDataToString());
}
private void ResolveConflict(IConflictResolver resolver, ISavedGameMetadata original, byte[] originalData, ISavedGameMetadata unmerged, byte[] unmergedData)
{
if (originalData == null)
resolver.ChooseMetadata(unmerged);
else if (unmergedData == null)
resolver.ChooseMetadata(original);
else
{
string originalStr = Encoding.ASCII.GetString(originalData);
string unmergedStr = Encoding.ASCII.GetString(unmergedData);
int originalNum = int.Parse(originalStr);
int unmergedNum = int.Parse(unmergedStr);
if(originalNum > unmergedNum)
{
resolver.ChooseMetadata(original);
return;
}
else if (unmergedNum > originalNum)
{
resolver.ChooseMetadata(unmerged);
return;
}
resolver.ChooseMetadata(original);
}
}
private void OnSavedGameOpened(SavedGameRequestStatus status, ISavedGameMetadata game)
{
if(status == SavedGameRequestStatus.Success)
{
if (!isSaving)
LoadGame(game);
else
SaveGame(game);
}
else
{
if (!isSaving)
LoadLocal();
else
SaveLocal();
}
}
private void LoadGame(ISavedGameMetadata game)
{
((PlayGamesPlatform)Social.Active).SavedGame.ReadBinaryData(game, OnSavedGameDataRead);
}
private void SaveGame(ISavedGameMetadata game)
{
string stringToSave = GameDataToString();
PlayerPrefs.SetString(Save_Name, stringToSave);
byte[] dataToSave = Encoding.ASCII.GetBytes(stringToSave);
SavedGameMetadataUpdate update = new SavedGameMetadataUpdate.Builder().Build();
((PlayGamesPlatform)Social.Active).SavedGame.CommitUpdate(game, update, dataToSave, OnSavedGameDataWritten);
}
private void OnSavedGameDataRead(SavedGameRequestStatus status, byte[] savedData)
{
if(status == SavedGameRequestStatus.Success)
{
string cloudDataString;
if (savedData.Length == 0)
cloudDataString = "0";
else
cloudDataString = Encoding.ASCII.GetString(savedData);
string localDataString = PlayerPrefs.GetString(Save_Name);
StringToGameData(cloudDataString, localDataString);
}
}
private void OnSavedGameDataWritten(SavedGameRequestStatus status, ISavedGameMetadata game)
{
}
#endregion /Saved Games
}
Basically I want to launch an event when a string reaches a specific length.
I have a Static String
Static String _Info;
So i have My Delegate that has an integer as a Parameter !
public Delegate void ReachLengthHandler(int Length);
and My event :
public event ReachLengthHandler ReachLengthEvent;
And a Method that Keep addingSome informations to that string :
public void AddInfo()
{
new Thread(() =>
{
while(true)
_Info += ""; //Basically add the inputs of the user here !
if (_Info.Length > 500)
{
if (ReachLengthEvent != null)
ReachLengthEvent(_Info.Length);
}
}).Start();
}
Do you think its the right way to do this event or there are any cleaner ways ?
EDIT :
I want this event because I want to save this string in a Database table row so I don't want to expand the possible size of a row !
As some pointed out in the comments, you may be trying to solve an instance of the XY Problem -- but assuming you're not, you are not approaching things in an object-oriented way, starting with encapsulation.
This could be a start, FWIW:
public class MaxLengthEventArgs : EventArgs
{
public MaxLengthEventArgs(string value)
{
LastAppended = value;
}
public string LastAppended { get; private set; }
}
public delegate void MaxLengthEventHandler(object sender, MaxLengthEventArgs args);
public class StringAccumulator
{
protected StringBuilder Builder { get; private set; }
public StringAccumulator(int maxLength)
{
if (maxLength < 0)
{
throw new ArgumentOutOfRangeException("maxLength", "must be positive");
}
Builder = new StringBuilder();
MaxLength = maxLength;
}
public StringAccumulator Append(string value)
{
if (!string.IsNullOrEmpty(value))
{
var sofar = value.Length + Builder.Length;
if (sofar <= MaxLength)
{
Builder.Append(value);
if ((OnMaxLength != null) && (sofar == MaxLength))
{
OnMaxLength(this, new MaxLengthEventArgs(value));
}
}
else
{
throw new InvalidOperationException("overflow");
}
}
return this;
}
public override string ToString()
{
return Builder.ToString();
}
public int MaxLength { get; private set; }
public event MaxLengthEventHandler OnMaxLength;
}
class Program
{
static void Test(object sender, MaxLengthEventArgs args)
{
var acc = (StringAccumulator)sender;
Console.WriteLine(#"max length ({0}) reached with ""{1}"" : ""{2}""", acc.MaxLength, args.LastAppended, acc.ToString());
}
public static void Main(string[] args)
{
var acc = new StringAccumulator(10);
try
{
acc.OnMaxLength += Test;
acc.Append("abc");
acc.Append("def");
acc.Append("ghij");
Console.WriteLine();
acc.Append("ouch...");
Console.WriteLine("(I won't show)");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
}
Also, keep in mind that strings in .NET are immutable.
Accumulating them using string concatenation, as you did in
_Info += ""
... isn't going to scale well (performance-wise).
'HTH,
Usually eventhandler is used with specific signature.
public delegate void ReachLengthHandler(object sender, EventArgs args);
class Program
{
public event ReachLengthHandler handler;
private const int Threshhold = 500;
public string Info
{
set
{
if (value.Length > Threshhold)
{
this.OnReachLength(null);
}
}
}
public void OnReachLength(EventArgs args)
{
this.handler?.Invoke(this, args);
}
}
I have the following:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button3_Click(object sender, EventArgs e)
{
try
{
var strExpression = #"
import sys
sys.stdout=my.write
print 'ABC'
";
var engine = Python.CreateEngine();
var scope = engine.CreateScope();
var sourceCode = engine.CreateScriptSourceFromString(strExpression);
scope.SetVariable("my", this);
var actual = sourceCode.Execute<string>(scope);
textBox1.Text += actual;
}
catch (System.Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
public void write(string s)
{
textBox1.Text += s;
}
}
But I am getting an Exception that says there is no write.
What am I doing incorrectly?
You can set a stream and a textwriter directly from c#:
engine.Runtime.IO.SetOutput(stream, txtWriter);
engine.Runtime.IO.SetErrorOutput(stream, txtWriter);
To redirect the output for example you could override TextWriter class with a new one writing on your textbox.
e.g.
in my application I did an override of StreamWriter class that rises events when something is written on the stream (here just a part of the code):
public class MyEvtArgs<T> : EventArgs
{
public T Value
{
get;
private set;
}
public MyEvtArgs(T value)
{
this.Value = value;
}
}
public class EventRaisingStreamWriter : StreamWriter
{
#region Event
public event EventHandler<MyEvtArgs<string>> StringWritten;
#endregion
#region CTOR
public EventRaisingStreamWriter(Stream s):base(s)
{ }
#endregion
#region Private Methods
private void LaunchEvent(string txtWritten)
{
if (StringWritten != null)
{
StringWritten(this, new MyEvtArgs<string>(txtWritten));
}
}
#endregion
#region Overrides
public override void Write(string value)
{
base.Write(value);
LaunchEvent(value);
}
public override void Write(bool value)
{
base.Write(value);
LaunchEvent(value.ToString());
}
// here override all writing methods...
#endregion
}
Then in your application you should just do something like:
MemoryStream ms = new MemoryStream();
EventRaisingStreamWriter outputWr = new EventRaisingStreamWriter(ms);
outputWr.StringWritten += new EventHandler<MyEvtArgs<string>>(sWr_StringWritten);
var engine = Python.CreateEngine();
engine.Runtime.IO.SetOutput(ms, outputWr);
engine.CreateScriptSourceFromString("print 'hello world!'").Execute();
void sWr_StringWritten(object sender, MyEvtArgs<string> e)
{
textBox1.Text += e.Value;
}
Your example is close to working.
The problem you saw is because sys.stdout=my.write should be sys.stdout=my.
It also appears that Python expects to find a boolean softspace attribute.
I have made these two changes in the code below. Hopefully this should now work as you expected.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button3_Click(object sender, EventArgs e)
{
try
{
var strExpression = #"
import sys
sys.stdout=my
print 'ABC' ";
var engine = Python.CreateEngine();
var scope = engine.CreateScope();
var sourceCode = engine.CreateScriptSourceFromString(strExpression);
scope.SetVariable("my", this);
var actual = sourceCode.Execute(scope);
textBox1.Text += actual;
} catch (System.Exception ex) {
MessageBox.Show(ex.ToString());
}
}
public bool softspace;
public void write(string s)
{
textBox1.Text += s;
}
}
This worked fine for me
pyRuntime = Python.CreateRuntime();
pyRuntime.IO.SetOutput(Console.OpenStandardOutput(), new UTF8Encoding(true, false));