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

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

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

Сообщение adamix »

Плагин, позволяющий писать плагины для 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 »

Ну и под конец дня, доделал вторую тык сказать версию, с новыми примерами и 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 »

Новая версия, обновил шапку, добавил некоторую документацию.
yaotzin
Сообщения: 105
Зарегистрирован: 01:38, 21.07.2008
Контактная информация:

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

Сообщение yaotzin »

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

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

Сообщение adamix »

yaotzin писал(а):эх... когдато я такое искал. получается плагин чтоб можно было писать плагины на С# ? прикольно
На любом .Net-языке. C#/VB.Net/IronPython/IronRuby
Аватара пользователя
Jenya-Grin
Сообщения: 356
Зарегистрирован: 20:30, 22.09.2011
Откуда: Украина, г.Бердичев

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

Сообщение Jenya-Grin »

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

Разве нельзя сделать это аналогичным как с Delphi \ C++?
Аватара пользователя
SV
Сообщения: 797
Зарегистрирован: 00:11, 06.09.2010
Откуда: Киров

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

Сообщение SV »

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

Разве нельзя сделать это аналогичным как с Delphi \ C++?
Можно, не все знаю Delphi & C++
Аватара пользователя
Jenya-Grin
Сообщения: 356
Зарегистрирован: 20:30, 22.09.2011
Откуда: Украина, г.Бердичев

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

Сообщение Jenya-Grin »

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

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

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

Сообщение SV »

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

Как бы сконвертировать из C++ в C# целиком плагин.
На сколько я помню в C# свои особенности написания dll чем C++ или в этом же delphi.
Ответить