Работает с помощью свободного аналога .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
Код: Выделить всё
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);
}
}
}
}
}
Пример скрипта-редиректера:
Код: Выделить всё
// 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());
}
}
}
}