Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Страница 1 из 3 123 ПоследняяПоследняя
Показано с 1 по 10 из 21

Тема: .NET Plugin

  1. #1
    Аватар для Seregamil
    Проверенный

    Статус
    Оффлайн
    Регистрация
    21.11.2013
    Сообщений
    551
    Репутация:
    272 ±

    .NET Plugin

    Просьба не закидывать помидорками, я старался.

    Подавая заявку в проф.лигу LightCode Cup возникла мысль, что, возможно, будет написание плагинов. Написать годный плагин на крестах за короткий промежуток времени я не способен, поэтому решил восстановить свою старую работу по какой-никакой попытке написания плагинов в среде .NET

    И так. Данная разработка позволит вам писать плагины на C# и полноценно использовать их.

    Функции на стороне сервера:

     callDotnetMethod

    Вызывает метод плагина.
    Параметры:
    methodName - имя вызываемого метода
    split[] - ключ для параметров
    i - int32
    f - float
    s - string
    c - char
    {Float,_}:... - аргументы соответственно
    Возвращаемые значения:

    int32,
    boolean,
    float

     callDotnetMethodStr

    Из-за неспособности AMX машины вернуть текстовый параметр пришлось создавать аналогичную предыдущей функцию.
    Разница только в параметрах. Возвращается всегда 1.

    Параметры:
    methodName - имя вызываемого метода
    split[] - ключ для параметров
    i - int32
    f - float
    s - string
    c - char
    str[] - массив для записи текста
    length - размер массива
    {Float,_}:... - аргументы соответственно


    Функции на стороне плагина:

     cpp.callRemoteCallback

    Вызывает каллбэк по его названию и передает параметры.
    Параметры:

    string callback - название каллбэка
    params object[] args - аргументы


     cpp.logwrite

    Выводит текст в консоль
    Параметры:

    string text - текст =)


     Пример использования этих функций

     pawn

    PHP код:
    #include <a_samp>

    native callDotnetMethod(methodName[], split[], {Float,_}:...);
    native callDotnetMethodStr(methodName[], str[], lensplit[], {Float,_}:...);

    main(){

    }

    public 
    OnGameModeInit() {
        
    callDotnetMethod("onDotnetLoaded""cf"'v'1.0);

        new 
    temp_int callDotnetMethod("kernel.testINT""ii"1024);
        
    printf("testINT returned: %i"temp_int);
        
        new 
    temp_bool callDotnetMethod("kernel.testBOOL""isi"1"boolean=)"0);
        
    printf("testBOOL returned: %i"temp_bool);
        
        new 
    temp_float callDotnetMethod("kernel.testFLOAT""ifcf"101.432'c'242);
        
    printf("testFLOAT returned: %f"temp_float);
        
        new 
    temp_str16 ] ;
        
    callDotnetMethodStr("kernel.testSTRING"temp_strsizeof temp_str"sss""by""Seregamil""dotNET v1.0");
        
    printf("testSTRING returned: %s"temp_str);
        return 
    true ;
    }

    forward onDotnetWasLoaded(str[]);
    public 
    onDotnetWasLoaded(str[]){
        print(
    str);


     kernel.cs

    PHP код:
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Runtime.InteropServices;
    using System.Threading;
    using System.Net;
    using System.Net.Sockets;
    using System.IO;

    namespace 
    c_sharp
    {
        public class 
    kernel
        
    {
            public static 
    object onDotnetLoaded(params object[] args)
            {
                
    cpp.logwrite("dotnet-> onDotnetLoaded was called. ARGS:");
                foreach (
    object arg in args)
                {
                    
    cpp.logwrite(arg.ToString());
                }

                
    cpp.callRemoteCallback("onDotnetWasLoaded""Hello! =)");
                return 
    true;
            }

            public static 
    object testINT(params object[] args)
            {
                
    cpp.logwrite("dotnet-> testINT was called");
                
    int a Convert.ToInt32(args[0]);
                
    int b Convert.ToInt32(args[1]);
                return 
    ;
            }

            public static 
    object testBOOL(params object[] args)
            {
                
    cpp.logwrite("dotnet-> testBOOL was called.");
                return 
    false;
            }

            public static 
    object testSTRING(params object[] args)
            {
                
    cpp.logwrite("dotnet-> testSTRING was called." );

                foreach (
    object arg in args)
                {
                    
    cpp.logwrite(string.Format("{0}: {1}",arg.GetType(), arg.ToString()));
                }

                return 
    "blackJack prod.";
            }

            public static 
    object testFLOAT(params object[] args)
            {
                
    cpp.logwrite("dotnet-> testFLOAT was called. ARGS:");
                
    float result 13.228f;
                return 
    result;
            }
        }


     result



    Решение содержит 2 проекта. Первый на C#, второй на C++. Это COM сборка. При компиляции образуется один *.dll файл в нужной директории. В моем случае это S:\gta-o\plugins\.
    Я использую VS2012 Express. Путь для вывода меняется в свойствах проекта dotnet

     Смотрим

    Второй этап - нужно указать местоположение файла c_sharp.tlb.
    7 строка проекта dotnet
    #import "C:\Users\Seregamil\Documents\GitHub\.NET-plugin\source\c_sharp\bin\Debug\c_sharp.tlb" raw_interfaces_only

    ВНИМАНИЕ. КОМПИЛЯЦИЯ ПРОЕКТА ПРОИЗВОДИТСЯ В РЕЖИМЕ АДМИНИСТРАТОРА

    Всё. Вы готовы к разработке плагина на C#.
    Все примеры я делал в файле kernel.cs, если хотите - меняйте, делайте зависимость и т.д. у вас нет ограничений.
    Файл macro.cs содержит значения MAX_PLAYERS, MAX_VEHICLES etc., использовалось для написания и синхронизации плагина с клиентской частью игрока.

    * Я не стал прикручивать SAMPGDK, т.к. мне он не нужен. Основная задача - написание плагинов, а не гейммодов. На офф.форуме есть плагин, позволяющий писать мод на C#
    * Я умышленно отключил mono. Хотите писать плагин под Linux - пожалуйста, прикручивается это легко, достаточно поставить библиотеки и перекомпилировать проект.

    Ссылка на разработку. Примеры прилагаются https://github.com/Seregamil/.NET-plugin

    Огромное спасибо пользователям SDraw, Disinterpreter, g3o0or, Fallen A. за помощь.
    Последний раз редактировалось Seregamil; 21.12.2015 в 17:13.

  2. 4 пользователя(ей) сказали cпасибо:
    $continue$ (18.12.2015)Desulaid (18.12.2015)Nurick (19.12.2015)Zaur_Lumanov (06.02.2016)
  3. #2
    Аватар для Daniel_Cortez
    new fuck_logic[0] = EOS;

    Статус
    Онлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    1,760
    Репутация:
    2252 ±
    В текущем виде, чтобы юзать функции на C#, нужно копипастить таблицу из исходника на C# в .pwn. Крайне ненадёжно. Если захочешь добавить в плагин новую функцию (которую ещё не факт, что будешь использовать в скрипте на Pawn), придётся заново копипастить таблицу. ИЧСХ, рано или поздно забудешь это сделать и в лучшем случае лицезреешь какой-нибудь сообщение об ошибке или краш.
    Хотя, можно было с самого начала добавить в плагин таблицу из названий и адресов функций (как в плагинах на C/C++) и сделать из Pawn вызов функции на C# по имени, а не по ID.
    Индивидуально в PM и Skype по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).
    SA-MP 0.4 is a lie

  4. #3
    Аватар для Seregamil
    Проверенный

    Статус
    Оффлайн
    Регистрация
    21.11.2013
    Сообщений
    551
    Репутация:
    272 ±
    Цитата Сообщение от Daniel_Cortez Посмотреть сообщение
    В текущем виде, чтобы юзать функции на C#, нужно копипастить таблицу из исходника на C# в .pwn. Крайне ненадёжно. Если захочешь добавить в плагин новую функцию (которую ещё не факт, что будешь использовать в скрипте на Pawn), придётся заново копипастить таблицу. ИЧСХ, рано или поздно забудешь это сделать и в лучшем случае лицезреешь какой-нибудь сообщение об ошибке или краш.
    Хотя, можно было с самого начала добавить в плагин таблицу из названий и адресов функций (как в плагинах на C/C++) и сделать из Pawn вызов функции на C# по имени, а не по ID.
    Во всем этом деле копипастится одно -
    PHP код:
    enum c_sharp {
        
    onDotnetLoaded,
        
    testINT,
        
    testBOOL,
        
    testSTRING,
        
    testFLOAT
    }; 
    Изначально было так, что вызывалось по названию, но всё-равно придется делать таблицу, ибо вызвать метод по названию невозможно.

  5. #4
    Аватар для $continue$
    Заблокирован

    Статус
    Оффлайн
    Регистрация
    02.08.2014
    Адрес
    г. Киров (aka Вятка)
    Сообщений
    1,466
    Репутация:
    265 ±
    Каким образом если не секрет (.cpp) файл используется в С#?

  6. #5
    Аватар для Seregamil
    Проверенный

    Статус
    Оффлайн
    Регистрация
    21.11.2013
    Сообщений
    551
    Репутация:
    272 ±
    Цитата Сообщение от $continue$ Посмотреть сообщение
    Каким образом если не секрет (.cpp) файл используется в С#?
    *.cpp файлы в C# не используются. Я просто связал 2 проекта в один.

  7. #6
    Аватар для Seregamil
    Проверенный

    Статус
    Оффлайн
    Регистрация
    21.11.2013
    Сообщений
    551
    Репутация:
    272 ±
    Обновил библиотеку. Нашел способ вызывать метод по его названию не прибегая к использованию таблицы.

    native callDotnetMethod(methodName[], split[], {Float,_}:...);
    native callDotnetMethodStr(methodName[], str[], len, split[], {Float,_}:...);


    Обновил тему. Сейчас займусь обновлением примеров.

  8. #7
    Аватар для $continue$
    Заблокирован

    Статус
    Оффлайн
    Регистрация
    02.08.2014
    Адрес
    г. Киров (aka Вятка)
    Сообщений
    1,466
    Репутация:
    265 ±
    Цитата Сообщение от Seregamil Посмотреть сообщение
    *.cpp файлы в C# не используются. Я просто связал 2 проекта в один.
    Окей. Задам вопрос по другому: У тебя функции из С++ используются в C#?
    Если да, то как? Динамическая библиотека?

  9. #8
    Аватар для Seregamil
    Проверенный

    Статус
    Оффлайн
    Регистрация
    21.11.2013
    Сообщений
    551
    Репутация:
    272 ±
    Цитата Сообщение от $continue$ Посмотреть сообщение
    Окей. Задам вопрос по другому: У тебя функции из С++ используются в C#?
    Если да, то как? Динамическая библиотека?
    https://ru.wikipedia.org/wiki/Component_Object_Model

  10. Пользователь сказал cпасибо:
    $continue$ (20.12.2015)
  11. #9
    Аватар для Seregamil
    Проверенный

    Статус
    Оффлайн
    Регистрация
    21.11.2013
    Сообщений
    551
    Репутация:
    272 ±
    Теперь можно вызывать метод из любого класса. Т.е. если раньше было ограничение на нахождение метода в классе, то сейчас - вообще всё-равно.
    Пример:
    PHP код:
    callDotnetMethod"player.GetName" );
    callDotnetMethod"vehicle.SetPos" ); 
    На мой взгляд это удобнее и позволит разделять проект на множество различных классов, а не держать всё в куче.

    А, да, добавлен .gitignore, дабы не засирать проект.

  12. #10
    Аватар для Seregamil
    Проверенный

    Статус
    Оффлайн
    Регистрация
    21.11.2013
    Сообщений
    551
    Репутация:
    272 ±
    Добавил пример для работы с регулярными выражениями.

 

 
Страница 1 из 3 123 ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •