C# like events in D programming language - events

I recently finished a 6-month internship at a company that uses C# for the most part of their programming. During this time I first used and got accustomed to the C# way of doing events. Like shown below:
acc.AccountBalanceLow += new AccountBalanceDelegate(atm.AccountToLow);
acc.AccountBalanceLow +=new AccountBalanceDelegate(atm.AccountToLowAgain);
Does D support such constructs? I'd imagine one could be created by the user by using operator overloading, but I'm not entirely sure. If it's not possible what would then be a common excepted way of doing it then?

The equivalent construct in D is to use Signals and Slots. This is a different means of implementing the Observer Pattern, which is effectively what a C# event does.

D (and C++) use an analogous pattern called signals and slots.

If you're feeling the need to use the C# style-events instead of signals and slots, they're extremely simple to implement:
module fluidity.core.event;
class Event {
alias void delegate(EventArgs) handler_t;
handler_t[] handlers;
Object owner;
this() {}
this(Object o) { owner = o; }
void attach(handler_t handler) {
if (handler)
handlers ~= handler;
}
void detach(handler_t handler) {
int i = -1;
foreach (j, h; handlers)
{
if (h is handler)
{
i = j;
break;
}
}
if (i > -1)
handlers = handlers[0..i] ~ handlers[i+1..$];
}
void raise() { raise(new EventArgs(owner)); }
void raise(EventArgs e) {
// call all handlers
foreach (handler; handlers)
{
if (handler)
handler(e);
}
}
void opAddAssign(handler_t handler) {
attach(handler);
}
void opSubAssign(handler_t handler) {
detach(handler);
}
}
class EventArgs {
Object source;
bool handled;
void handle() { handled = true; }
this() {}
this(Object s) {
source = s;
}
}

Here is an example of c# style events using signals, slots, and a templates:
events.d:
import std.signals;
class Event(T...){
mixin Signal!(T);
void broadcast(T args){
emit(args);
}
void opAddAssign(slot_t slot){
connect(slot);
}
void opSubAssign(slot_t slot) {
disconnect(slot);
}
}
declaration:
public Event!(int) onSomeEventOfInt;
public Event!(string, int) onSomeEventOfStringAndInt;
instantiation:
this.onSomeEventOfInt = new Event!(int)();
this.onSomeEventOfStringAndInt = new Event!(string, int)();
fire event:
int i = 4;
string str = "hello";
this.onSomeEventOfInt.broadcast(i);
this.onSomeEventOfStringAndInt.broadcast(str, 4);
observer registration:
obj1.onSomeEventOfInt += &handleEventOfInt
obj1.onSomeEventOfStringAndInt += &handleEventOfStringAndInt
void handleEventOfInt(int g)
{ /*do something */ }
void handleEventOfStringAndInt(string str, int g)
{ /*do something */ }

Check out DFL's event system. It works EXACTLY the same way as C# .NET.
DFL Event Example
Download DFL, grab the events module and use it the way you like. I modified it to use variadic template arguments. This gives maximum flexibility.
http://www.dprogramming.com/dfl098.zip

Related

Moving comparisons out from the Update method: using delegates instead or another approach?

Let's go straight to an example. Let's say we have:
Update(){
if (value.Equals("circular")) moveGameObjectInACircularWay();
else if (value.Equals("linear")) moveGameObjectInALinearWay();
}
I think that is not very elegant solution. Unity needs to perform a comparison every frame. That does not sound very optimal to me. I'm just guessing it should be some other way to implement the same like:
Start () {
if (value.Equals("circular")) movement += moveGameObjectInACircularWay;
else if (value.Equals("linear")) movement += moveGameObjectInALinearWay;
}
Update () {
movement();
}
I guess the solution is related with delegates. That's why my proposed solution looks like delegates. I don't understand what delegates are well yet.
From MSDN "A delegate in C# is similar to a function pointer in C or C++. Using a delegate allows the programmer to encapsulate a reference to a method inside a delegate object." (https://msdn.microsoft.com/en-us/library/aa288459(v=vs.71).aspx) In short is a pointer to a method. What you want to do is the following:
using UnityEngine;
using System.Collections;
public delegate void MovementDelegate();
public class Movement : MonoBehaviour {
MovementDelegate movementFunction=null;
public string value = "linear";
void Start () {
if (value.Equals("circular")) movementFunction = moveGameObjectInACircularWay;
else if (value.Equals("linear")) movementFunction = moveGameObjectInALinearWay;
}
// Update is called once per frame
void Update()
{
if (movementFunction != null)
{
movementFunction();
}
}
void moveGameObjectInACircularWay()
{
Debug.Log("do circular movement here");
}
void moveGameObjectInALinearWay()
{
Debug.Log("do linear movement here");
}
}
The functions you declare must have the same signature as the delegate signature. If you want to add parameters to it, ex. an int, decalre your delegate as
public delegate void MovementDelegate(int speed);
and your implementation functions as
void moveGameObjectInACircularWay(int speed)
void moveGameObjectInALinearWay(int speed)
and change the call to
movementFunction(yourIntHere)
UPDATED!: Thanks to Joe Blow suggestion here is another solution:
public class Movement : MonoBehaviour
{
Action<int> movementFunction = null;
public string value = "linear";
void Start()
{
if (value.Equals("circular")) movementFunction = moveGameObjectInACircularWay;
else if (value.Equals("linear")) movementFunction = moveGameObjectInALinearWay;
}
// Update is called once per frame
void Update()
{
if (movementFunction != null)
{
movementFunction(2);
}
}
void moveGameObjectInACircularWay(int speed)
{
Debug.Log("do circular movement here "+ speed);
}
void moveGameObjectInALinearWay(int speed)
{
Debug.Log("do linear movement here " + speed);
}
}
My favorite answer has been written by Joe Blow in the comments:
Unity is components based. We better switch to Component-Based Thinking instead working with delegates.
So make two (or more) different scripts, and put those on the game object in question. Then, turn on and off these components as you wish.
So we would have to scripts added to our game object: MoveGameObjectInACircularWay.cs and MoveGameObjectInALinearWay.cs. Then a MainGameObjectScript.cs also added to our game object with the following code:
void Start () {
GetComponent()<MoveGameObjectInACircularWay>.active = true;
GetComponent()<MoveGameObjectInALinearWay>.active = false;
}

Console.ReadLine() passed to C# event

I'm learning RX and would like to use Console.ReadLine as a source for observable sequences.
I know that I can create "IEnumerable" using "yield return", but for my concrete use case I've decided to create a C# event, so that potentially many observers will be able to share the same keyboard input.
Here is my code:
class Program
{
private delegate void OnNewInputLineHandler(string line);
private static event OnNewInputLineHandler OnNewInputLineEvent = _ => {};
static void Main(string[] args)
{
Task.Run((Action) GetInput);
var input = ConsoleInput();
input.Subscribe(s=>Console.WriteLine("1: " + s));
Thread.Sleep(30000);
}
private static void GetInput()
{
while (true)
OnNewInputLineEvent(Console.ReadLine());
}
private static IObservable<string> ConsoleInput()
{
return Observable.Create<string>(
(IObserver<string> observer) =>
{
OnNewInputLineHandler h = observer.OnNext;
OnNewInputLineEvent += h;
return Disposable.Create(() => { OnNewInputLineEvent -= h; });
});
}
}
My problem - when I run the GetInput method as it is shown above, the very first input line is not sent to the sequence (but it is sent to the event handler).
However, if I replace it with the following version, everything works as expected:
private static void GetInput()
{
while (true)
{
var s = Console.ReadLine();
OnNewInputLineEvent(s);
}
}
Could someone shed some light on why this might happen?
You're trying to make life difficult for yourself. There is almost always a way to make things simple with Rx. It's just a matter of learning to think more functionally rather than procedurally.
This is all you need:
class Program
{
static void Main(string[] args)
{
var subscription = ConsoleInput().Subscribe(s => Console.WriteLine("1: " + s));
Thread.Sleep(30000);
subscription.Dispose();
}
private static IObservable<string> ConsoleInput()
{
return
Observable
.FromAsync(() => Console.In.ReadLineAsync())
.Repeat()
.Publish()
.RefCount()
.SubscribeOn(Scheduler.Default);
}
}
This lets multiple subscribers share the one input through the .Publish().RefCount(). And the .SubscribeOn(Scheduler.Default) pushes the subscription out to a new thread - without it you block on a subscription.
If you move Task.Run((Action) GetInput); to after the subscription your code will work as desired. This is because in your original version, the first call of OnNewInputEvent(Console.ReadLine()) is run before you've hooked OnNewInputLineEvent to the observer.OnNext.

Class method callbacks in D to C functions

I'm writing a simple, lightweight engine in D. For the input calls I use GLFW3. The library in question uses callbacks to send input events to the program.
What I would like is to use a method from a class as the callback function, rather than a function. This is proving difficult (just as it is in C++). I believe there is an elegant way to do it, but this is how I got it right now.
public void initialise(string logPath) {
[...]
m_Window = new RenderWindow();
m_Window.create();
// Lets set up the input loop.
GLFWkeyfun keyCB = function(GLFWwindow* win, int key, int scancode, int action, int mods) {
printf("Got key event: %d:%d:%d:%d\n");
RenderWindow rw = Root().getRenderWindow();
switch (key) {
case KeyboardKeyID.Q:
glfwSetWindowShouldClose(win, true);
break;
case KeyboardKeyID.H:
if (rw.hidden) {
rw.show();
} else {
rw.hide();
}
break;
default:
break;
}
};
glfwSetKeyCallback(m_Window.window, keyCB);
}
Here is the definition of the callback setting function and type:
extern (C) {
alias GLFWkeyfun = void function(GLFWwindow*, int, int, int, int);
GLFWkeyfun glfwSetKeyCallback(GLFWwindow*, GLFWkeyfun);
}
What I would like to do instead, is create a method that is part of the class. Is there any way to do this?
A solution I tried was a static method wrapped around in extern (C), this worked for calling it, but then I could (obviously) not access this or any other methods, which defeats the point of the exercise.
Thanks in advance.
The way I'd do it is to have a static map of the pointers to the class, so like:
static YourWindowClass[GLFWwindow*] mappings;
Then, in the constructor, once you get a GLFWwindow pointer, add it right in:
mappings[m_Window.window] = this;
Now, make the static extern(C) function to use as the callback. When it gets a pointer from C, look up your class reference in that mappings array and then go ahead and call the member function through that, forwarding the arguments.
So a bit of an extra step, but since it doesn't look like the callback lets you pass user-defined data to it (BTW, attention all lib writers: user-defined void* to the callbacks is sooooo useful, you should do it whenever possible!), but since it doesn't do that the associative array is the next best thing.
Well, I have figured it out my own. The solution I went with was a Singleton class InputManager. Instances of RenderWindow attach themselves to it with the following function. The InputManager then creates an anonymous function() for the RenderWindow that receives events, which then calls a function that handles the actual event.
The idea is then that listeners attach themselves to the InputManager and receive keyboard events for the RenderWindow they requested.
class InputManager {
private static InputManager m_Instance;
private RenderWindow[] m_Watched;
private KeyboardListener[][RenderWindow] m_KeyListeners;
public void recvKeyEvent(GLFWwindow* w, int k, int c, int a, int m) {
writeln("Received key: ", k);
}
public void watch(RenderWindow win) {
if (!isWatched(win)) {
// Relay the key callbacks onto the InputManager.
GLFWkeyfun keyCB = function(GLFWwindow* w, int k, int c, int a, int m) {
InputManager().recvKeyEvent(w, k, c, a, m);
};
glfwSetKeyCallback(win.window, keyCB);
}
}
private bool isWatched(RenderWindow win) {
foreach(RenderWindow w; m_Watched) {
if (win == w) {
return true;
}
}
return false;
}
public static InputManager opCall() {
if (m_Instance is null) {
m_Instance = new InputManager();
}
return m_Instance;
}
private this() {
// nothing
}
}
Works like a charm, now to figure out how to properly attach listeners elegantly.
For those curious, the full source code with how this is set up can be found at https://github.com/Adel92/Mage2D. I hope it helps someone else in a similar position with callbacks.

Can mousePressed be defined within a class?

I am trying to create a class called InputManager to handle mouse events. This requires that mousePressed be contained within the InputManager class.
like so
class InputManager{
void mousePressed(){
print(hit);
}
}
problem is, that doesn't work. mousePressed() only seems to work when it's outside the class.
How can I get these functions nicely contained in a class?
Try this:
in main sketch:
InputManager im;
void setup() {
im = new InputManager(this);
registerMethod("mouseEvent", im);
}
in InputManager Class:
class InputManager {
void mousePressed(MouseEvent e) {
// mousepressed handling code here...
}
void mouseEvent(MouseEvent e) {
switch(e.getAction()) {
case (MouseEvent.PRESS) :
mousePressed();
break;
case (MouseEvent.CLICK) :
mouseClicked();
break;
// other mouse events cases here...
}
}
}
Once you registered InputManger mouseEvent in PApplet you don't need to call it and it will be called each loop at the end of draw().
Most certainly, but you are responsible for ensuring it gets called:
interface P5EventClass {
void mousePressed();
void mouseMoved();
// ...
}
class InputManager implements P5EventClass {
// we MUST implement mousePressed, and any other interface method
void mousePressed() {
// do things here
}
}
// we're going to hand off all events to things in this list
ArrayList<P5EventClass> eventlisteners = new ArrayList<P5EventClass>();
void setup() {
// bind at least one input manager, but maybe more later on.
eventlisteners.add(new InputManager());
}
void draw() {
// ...
}
void mousePressed() {
// instead of handling input globally, we let
// the event handling obejct(s) take care of it
for(P5EventClass p5ec: eventlisteners) {
p5ec.mousePressed();
}
}
I would personally make it a bit tighter by also passing the event variables explicitly, so "void mousePressed(int x, int y);" in the interface and then calling "p5ec.mousePressed(mouseX, mouseY);" in the sketch body, simply because relying on globals rather than local variables makes your code prone to concurrency bugs.
The easiest way to do so would be:
class InputManager{
void mousePressed(){
print(hit);
}
}
InputManager im = new InputManager();
void setup() {
// ...
}
void draw() {
// ...
}
void mousePressed() {
im.mousePressed();
}
This should solve any problems you were having with variable scoping in your class.
Note: In the class, it doesn't even have to be named mousePressed, you can name it anything you wish, as long as you call it inside of the main mousePressed method.

Proper way of raising events from C++/CLI?

I was wondering what's the proper way of raising events from C++/CLI. In C# one should first make a copy of the handler, check if it's not null, and then call it. Is there a similar practice for C++/CLI?
This isn't the whole story! You don't usually have to worry about null event handlers in C++/CLI. The code for these checks is generated for you. Consider the following trivial C++/CLI class.
public ref class MyClass
{
public:
event System::EventHandler ^ MyEvent;
};
If you compile this class, and disassemble it using Reflector, you get the following c# code.
public class MyClass
{
// Fields
private EventHandler <backing_store>MyEvent;
// Events
public event EventHandler MyEvent
{
[MethodImpl(MethodImplOptions.Synchronized)] add
{
this.<backing_store>MyEvent = (EventHandler) Delegate.Combine(this.<backing_store>MyEvent, value);
}
[MethodImpl(MethodImplOptions.Synchronized)] remove
{
this.<backing_store>MyEvent = (EventHandler) Delegate.Remove(this.<backing_store>MyEvent, value);
}
raise
{
EventHandler <tmp> = null;
<tmp> = this.<backing_store>MyEvent;
if (<tmp> != null)
{
<tmp>(value0, value1);
}
}
}
}
The usual checks are being done in the raise method. Unless you really want custom behavior, you should feel comfortable declaring your event as in the above class, and raising it without fear of a null handler.
C++/CLI allows you to override raise in custom event handlers so you don't have to test for null or copy when raising the event. Of course, inside your custom raise you still have to do this.
Example, adapted from the MSDN for correctness:
public delegate void f(int);
public ref struct E {
f ^ _E;
public:
void handler(int i) {
System::Console::WriteLine(i);
}
E() {
_E = nullptr;
}
event f^ Event {
void add(f ^ d) {
_E += d;
}
void remove(f ^ d) {
_E -= d;
}
void raise(int i) {
f^ tmp = _E;
if (tmp) {
tmp->Invoke(i);
}
}
}
static void Go() {
E^ pE = gcnew E;
pE->Event += gcnew f(pE, &E::handler);
pE->Event(17);
}
};
int main() {
E::Go();
}
If your issue is that raise isn't private, then explicitly implement it like the docs say:
http://msdn.microsoft.com/en-us/library/5f3csfsa.aspx
In summary:
If you just use the event keyword, you create a "trivial" event. The compiler generates add/remove/raise and the delegate member for you. The generated raise function (as the docs say) checks for nullptr. Trivial events are documented here:
http://msdn.microsoft.com/en-us/library/4b612y2s.aspx
If you want "more control", for example to make raise private, then you have to explicitly implement the members as shown in the link. You must explicitly declare a data member for the delegate type. Then you use the event keyword to declare the event-related members, as in the Microsoft example:
// event keyword introduces the scope wherein I'm defining the required methods
// "f" is my delegate type
// "Event" is the unrealistic name of the event itself
event f^ Event
{
// add is public (because the event block is public)
// "_E" is the private delegate data member of type "f"
void add(f ^ d) { _E += d; }
// making remove private
private:
void remove(f ^ d) { _E -= d; }
// making raise protected
protected:
void raise(int i)
{
// check for nullptr
if (_E)
{
_E->Invoke(i);
}
}
}// end event block
Wordy, but there it is.
-reilly.

Resources