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

Тема: .NET Plugin

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

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

    .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
    "Это не хак, это фича"

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

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

    Статус
    Оффлайн
    Регистрация
    21.11.2013
    Сообщений
    551
    Репутация:
    274 ±
    Цитата Сообщение от 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,487
    Репутация:
    276 ±
    Каким образом если не секрет (.cpp) файл используется в С#?
    Value your freedom or you will lose it, teaches history. "Don't bother us with politics," respond those who don't want to learn. (c) Richard Stallman

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

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

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

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

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


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

  8. #7
    Аватар для $continue$
    Пользователь

    Статус
    Оффлайн
    Регистрация
    02.08.2014
    Адрес
    г. Киров (aka Вятка)
    Сообщений
    1,487
    Репутация:
    276 ±
    Цитата Сообщение от Seregamil Посмотреть сообщение
    *.cpp файлы в C# не используются. Я просто связал 2 проекта в один.
    Окей. Задам вопрос по другому: У тебя функции из С++ используются в C#?
    Если да, то как? Динамическая библиотека?
    Value your freedom or you will lose it, teaches history. "Don't bother us with politics," respond those who don't want to learn. (c) Richard Stallman

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

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

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

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

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

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

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

 

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

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

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

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

Ваши права

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