CommFort xMono - пишем плагины на c#

Здесь обсуждаются технические аспекты создания дополнений.
adamix
Сообщения: 16
Зарегистрирован: 00:14, 06.02.2011

CommFort xMono - пишем плагины на c#

Сообщение adamix » 11:23, 30.01.2013

Плагин, позволяющий писать плагины для CommFort на .Net-языках.
Работает с помощью свободного аналога .Net - Mono(http://mono-project.com).
Суть работы: вызовы PluginProcess транслируются в .Net, при этом для обработки данных используются так называемые потоки(streams).
Вызовы к CommFortGetData и CommFortProcess транслируются из .Net в С.

Последняя версия: 0.4
http://unix-net.ru/install_cf_xmono_4.zip

Плагин может загружать неограниченное число .Net-плагинов внутрь себя, за это отвечает обертка CommFortMono.dll.
Плагины на .Net должны лежать в <client/server>/Plugins/.NET

Небольшая документация по интерфейсам внутри .Net:

Код: Выделить всё

CMFData:
int GetSize() - возвращает размер данных.
byte[] GetData() - возвращает данные.

CMFStream:
Create() - создает пусть поток для дальнейшей передачи данных программе.
Destroy() - удаляет поток, освобождает все занятые ресурсы.
WriteString(string str) - записывает строку в поток.
WriteInteger(int i) - записывает число в поток.
WriteData(byte[] b) - записывает данные в поток.

string ReadString() - читает строку из потока.
int ReadInteger() - читает число из потока.
CMFData ReadData() - читает данные из потока.

Reset() - переходит к началу потока, для повторного чтения.

CMFContext:
Call(int id, CMFStream stream) - вызывает функцию CommFort(аналог CommFortPluginProcess в С)
CMFStream GetData(int id, CMFStream stream) - получает данные от CommFort(аналог CommFortGetData в С)


События:

Код: Выделить всё

CommFortMono.Module.Load - вызывается при PluginStart, параметр: CMFContext ctx
CommFortMono.Module.Stop - вызывается при PluginStop.
CommFortMono.Module.Process - вызывается при PluginProcess, параметры: int id, CMFStream stream


Плагины на .Net должны быть приведены к интерфейсу:

Код: Выделить всё

    public interface IPlugin
    {
        // Вызывается при запуске .Net плагина
        void Main();
        // Вызывается в случае создания нового CMFContext
        void OnLoad(CMFContext ctx);
        // Вызывается при остановке xMono
        void OnStop();
        // Вызывается при PluginProcess
        void OnProcess(int id, CMFStream stream);
    }


Простенький плагин-редиректер:

Код: Выделить всё

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SamplePlugin
{
    public class Plugin : CommFortMono.IPlugin
    {
        public void Main()
        {
            Console.WriteLine("[Sample plugin]: Loaded");
        }
        public void OnStop()
        {

        }
        public void OnLoad(CMFContext ctx)
        {

        }
        public void OnProcess(int id, CMFStream stream)
        {
            if (id == 5)
            {
                string userName = stream.ReadString();
                string ipz = stream.ReadString();
                int userType = stream.ReadInteger();
                string chanName = stream.ReadString();
                int type = stream.ReadInteger();
                string text = stream.ReadString();

                if (chanName == "Общий")
                {
                    Console.WriteLine("message from username: " + userName);
                    stream = CMFStream.Create();
                    stream.WriteString("anshes and her friends");
                    stream.WriteInteger(0);
                    stream.WriteString("Сообщение на общем канале [" + userName + "]: " + text);
                    Module.GetContext().Call(50, stream);
                }
            }
        }
    }
}


Так же в поставке идет простенький интерпретатор C#-скриптов(ScriptingPlugin), скрипты должны быть в папке Plugins/.NET/Scripts, для загрузки скриптов вы должны быть прописаны как администратор в файле Plugins/.NET/Admin.xml
Пример скрипта-редиректера:

Код: Выделить всё

// Firstly load Xml assembly via small preprocessor definition

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using CommFortMono;

public class Script
{
   private string _fromChannel;
   private string _toChannel;
   public void Main()
   {
       //Module.Load += new Module.OnLoadHandler(OnLoad);
       //Module.Stop += new Module.OnStopHandler(OnStop);
       //Module.Process += new Module.OnProcessHandler(OnProcess);
      Module.Load += OnLoad;
      Module.Stop += OnStop;
      Module.Process += OnProcess;
      Console.WriteLine("[redirect.cs]: Loaded");
      XmlReader reader = XmlReader.Create("Plugins/.NET/Scripts/Redirect.xml");
      while(reader.Read())
      {
         if(reader.NodeType == XmlNodeType.Element && reader.Name == "Redirect")
         {
            _fromChannel = reader.GetAttribute(0);
            _toChannel = reader.GetAttribute(1);
            return;
         }
      }
   }
   
   public void Unload()
   {
      Module.Load -= OnLoad;
      Module.Stop -= OnStop;
      Module.Process -= OnProcess;
   }
   
   public void OnStop()
   {

   }
   public void OnLoad(CMFContext ctx)
   {

   }
   public void OnProcess(int id, CMFStream stream)
   {
      if (id == 5)
      {
         string userName = stream.ReadString();
         string ipz = stream.ReadString();
         int userType = stream.ReadInteger();
         string chanName = stream.ReadString();
         int type = stream.ReadInteger();
         string text = stream.ReadString();
         CMFData data = null;
         if(type == 2)
         {
            data = stream.ReadData();
         }
         
         
         if (chanName == _fromChannel)
         {
            stream = CMFStream.Create();
            stream.WriteString(_toChannel);
            stream.WriteInteger(0);
            stream.WriteString("[" + _fromChannel + "]: " + userName + ": " + text);
            Module.GetContext().Call(50, stream);
         }
         
         if(type == 2 && chanName == _fromChannel)
         {
            stream = CMFStream.Create();
            stream.WriteString(_toChannel);
            stream.WriteInteger(1);
            stream.WriteData(data.GetData());
            Module.GetContext().Call(51, stream);
            stream.Destroy();
            //File.WriteAllBytes("test.jpg", data.GetData());
         }
      }
   }
}


После этого в любом канале чата вы можете загрузить скрипт командой: !loadscript filename.cs
Последний раз редактировалось adamix 11:37, 05.02.2013, всего редактировалось 1 раз.

adamix
Сообщения: 16
Зарегистрирован: 00:14, 06.02.2011

Re: CommFort xMono - пишем плагины на c#

Сообщение adamix » 14:59, 30.01.2013

Ну и под конец дня, доделал вторую тык сказать версию, с новыми примерами и Evaluator'ом.
http://unix-net.ru/install_cf_xmono_2.zip

Пример использования эвалюатора:

Код: Выделить всё

[30.01.2013 14:55:34] SWAT - adamix: !parse using System; using CommFortMono;
[30.01.2013 14:55:57] SWAT - adamix: !parse var ctx = Module.GetContext(); var stream = CMFStream.Create();
[30.01.2013 14:56:26] SWAT - adamix: !parse stream.WriteString("Общий"); stream.WriteInteger(0); stream.WriteString("тест");
[30.01.2013 14:56:33] SWAT - adamix: !parse ctx.Call(50, stream);
[30.01.2013 14:56:33] SWAT - adamix: тест


Для работы плагина нужно поменять ник админа в Plugin.cs, которое в папке EvaluatePlugin.

adamix
Сообщения: 16
Зарегистрирован: 00:14, 06.02.2011

Re: CommFort xMono - пишем плагины на c#

Сообщение adamix » 11:37, 05.02.2013

Новая версия, обновил шапку, добавил некоторую документацию.

yaotzin
Сообщения: 105
Зарегистрирован: 01:38, 21.07.2008
Контактная информация:

Re: CommFort xMono - пишем плагины на c#

Сообщение yaotzin » 20:07, 23.03.2013

эх... когдато я такое искал. получается плагин чтоб можно было писать плагины на С# ? прикольно

adamix
Сообщения: 16
Зарегистрирован: 00:14, 06.02.2011

Re: CommFort xMono - пишем плагины на c#

Сообщение adamix » 13:30, 28.04.2013

yaotzin писал(а):эх... когдато я такое искал. получается плагин чтоб можно было писать плагины на С# ? прикольно


На любом .Net-языке. C#/VB.Net/IronPython/IronRuby

Аватара пользователя
Jenya-Grin
Сообщения: 356
Зарегистрирован: 20:30, 22.09.2011
Откуда: Украина, г.Бердичев

Re: CommFort xMono - пишем плагины на c#

Сообщение Jenya-Grin » 14:18, 29.04.2013

Блин, может бред пишу,
но ведь плагин это библиотека функции которой вызывает exe файл.

Разве нельзя сделать это аналогичным как с Delphi \ C++?

Аватара пользователя
SV
Сообщения: 797
Зарегистрирован: 00:11, 06.09.2010
Откуда: Киров

Re: CommFort xMono - пишем плагины на c#

Сообщение SV » 15:21, 29.04.2013

Jenya-Grin писал(а):Блин, может бред пишу,
но ведь плагин это библиотека функции которой вызывает exe файл.

Разве нельзя сделать это аналогичным как с Delphi \ C++?

Можно, не все знаю Delphi & C++

Аватара пользователя
Jenya-Grin
Сообщения: 356
Зарегистрирован: 20:30, 22.09.2011
Откуда: Украина, г.Бердичев

Re: CommFort xMono - пишем плагины на c#

Сообщение Jenya-Grin » 15:28, 29.04.2013

Я имею в виду чтоб чисто на C# принимать те же данные и создать те же функции в плагине.

Как бы сконвертировать из C++ в C# целиком плагин.

Аватара пользователя
SV
Сообщения: 797
Зарегистрирован: 00:11, 06.09.2010
Откуда: Киров

Re: CommFort xMono - пишем плагины на c#

Сообщение SV » 19:34, 29.04.2013

Jenya-Grin писал(а):Я имею в виду чтоб чисто на C# принимать те же данные и создать те же функции в плагине.

Как бы сконвертировать из C++ в C# целиком плагин.

На сколько я помню в C# свои особенности написания dll чем C++ или в этом же delphi.

Ответить