Crate for simple implementation of Component for Native API 1C:Enterprise written in rust

Overview

Гайд по использованию на русском языке можно посмотреть здесь и задать вопросы по использованию, но не оставляйте там комментарии об ошибках, т.к. там сложно это обсуждать. Лучше создайте issue в этом репозитории.

Library for simple 1C:Enterprise platform Native API Component development, originates from findings of this medigor/example-native-api-rs

Crate is tested on Linux and Windows. It should work on MacOS as well, but it is not tested.

Structure

Library is divided into two submodules:

  • native_api_1c_core describes all necessary for implementing 1C:Enterprise Native API
  • native_api_1c_macro provides a tool for significant simplification of component implementation, taking care of native_api_1c_core::interface::AddInWrapper property implementation

Usage

Attributes #[add_in_prop(...)]

  • name - property name in 1C
  • name_ru - property name in 1C in Russian
  • readable - property is readable from 1C
  • writable - property is writable from 1C

Available property types: i32, f64, bool, String

Functions or procedures #[add_in_func(...)]

  • name - property name in 1C
  • name_ru - property name in 1C in Russian

Input arguments, #[arg(...)], for each type of argument must be set, on of:

  • Int - i32
  • Float - f64
  • Bool - bool
  • Str - String
  • Date - chrono::DateTime<chrono::FixedOffset>
  • Blob - Vec<u8>

Return values, #[returns(...)], type must be set, one of:

  • Int - i32
  • Float - f64
  • Bool - bool
  • Str - String
  • Date - chrono::DateTime<chrono::FixedOffset>
  • Blob - Vec<u8>
  • None - () Additionally, Result<T, ()> can be used, where T is one of the above. In this case, result must be set in #[returns(...)] attribute: #[returns(Int, result)] for Result<i32, ()>

Example

# Cargo.toml
[package]
name = "my_addin"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
utf16_lit = "2.0"
native_api_1c = "0.10.3"
// src/lib.rs
use std::sync::Arc;

use native_api_1c::{native_api_1c_core::ffi::connection::Connection, native_api_1c_macro::AddIn};

#[derive(AddIn)]
pub struct MyAddIn {
    /// connection with 1C, used for calling events
    /// Arc is used to allow multiple threads to access the connection 
    #[add_in_con]
    connection: Arc<Option<&'static Connection>>, 

    /// Property, readable and writable from 1C
    #[add_in_prop(name = "MyProp", name_ru = "МоеСвойство", readable, writable)]
    pub some_prop: i32,

    /// Property, readable from 1C but not writable
    #[add_in_prop(name = "ProtectedProp", name_ru = "ЗащищенноеСвойство", readable)]
    pub protected_prop: i32,

    /// Function, taking one or two arguments and returning a result
    /// In 1C it can be called as:
    ///  ComponentObject.MyFunction(10, 15); // 2nd argument = 15
    ///  ComponentObject.MyFunction(10);     // 2nd argument = 12 (default value)
    /// If function returns an error, but does not panic, then 1C will throw an exception 
    #[add_in_func(name = "MyFunction", name_ru = "МояФункция")]
    #[arg(Int)]
    #[arg(Int, default = 12)]
    #[returns(Int, result)]
    pub my_function: fn(&Self, i32, i64) -> Result<i32, ()>,

    /// Function, taking no arguments and returning nothing 
    #[add_in_func(name = "MyProcedure", name_ru = "МояПроцедура")]
    pub my_procedure: fn(&mut Self),

    /// Private field, not visible from 1C
    private_field: i32,
}

impl MyAddIn {
    pub fn new() -> Self {
        Self {
            connection: Arc::new(None),
            some_prop: 0,
            protected_prop: 50,
            my_function: Self::my_function,
            my_procedure: Self::my_procedure,
            private_field: 100,
        }
    }

    fn my_function(&self, arg: i32, arg_maybe_default: i64) -> Result<i32, ()> {
        Ok(self.protected_prop
            + self.some_prop
            + arg
            + self.private_field
            + arg_maybe_default as i32)
    }

    fn my_procedure(&mut self) {
        self.protected_prop += 1;
    }
}
Comments
  • Вопросы по реализации - vtable и target

    Вопросы по реализации - vtable и target

    Хочу задать пару вопросов так как сам когда-то хотел реализовать подобный шаблон:

    1. Как реализовали уход от MSVC? Мне казалось, что для этого нужно соблюдение MSVC ABI. Но Rust основан на clang, а значит там llvm ABI. Я знаю, что компилятор Rust умеет собирать под MSVC ABI, но я не вижу в Cargo.toml или readme информации о таргетах;
    2. На каких операционных системах пробовал собрать? И какие контексты – клиентский или серверный?
    3. Поскольку API у 1С реализовано через наследование с virtual’ами, мне казалось, что нужно самому писать vtable’ы, чтоб платформа конкретно вызовы обрабатывала. Но в то же время, для винды мне казалось, что сборка выглядит как просто вызов функций из стандартной DLL’ки. Можешь помочь разобраться в vtable’ах? Я посмотрел сорцы и увидел код с memorymanagervtable. И хотел бы уточнить: a. Почему target_family = unix? b. Структура vtable’ов – implementation defined для компиляторов C++. Почему именно такая структура?
    documentation question 
    opened by bapho-bush 8
  • Проблема на Линукс

    Проблема на Линукс

    Снимок экрана от 2023-08-31 10-21-17 Добрый день на Линукс так и не хочет работать библиотека, не могу понять в чем дело. Ubuntu 22.04.3 LTS Тестил на платформе для Линукс. 1С:Предприятие 8.3, учебная версия (8.3.23.1688) &НаКлиенте Процедура НаписатьСообщение(Команда) Попытка НачатьУстановкуВнешнейКомпоненты(,"ОбщийМакет.VK"); Сообщить("ОК");
    Исключение Сообщить("Нет") КонецПопытки;
    ПодключитьВнешнююКомпонентуАсинх("ОбщийМакет.VK","Test2",ТипВнешнейКомпоненты.Native); ВК= Новый("AddIn.Test2.Test2"); Результат = ВК.ОбработатьДанные("Тел","ФИО"); Сообщить (Результат); КонецПроцедуры Результат на скриншоте Описание ошибки: Тип не определен (AddIn.Test2.Test2) {Документ.СвязьСКлиентом.Форма.ФормаДокумента.Форма(26)}:ВК= Новый("AddIn.Test2.Test2");

    [ОшибкаВоВремяВыполненияВстроенногоЯзыка, ОшибкаИспользованияВстроенногоЯзыка]

    Тестовый код

    use std::{ // fs::{metadata, File}, // io::Read, sync::Arc, }; use native_api_1c::{ native_api_1c_core::ffi::connection::Connection, native_api_1c_macro::AddIn };

    #[derive(AddIn)] pub struct Test2 { #[add_in_con] // соединение с 1С для вызова внешних событий connection: Arc<Option<&'static Connection>>, // Arc для возможности многопоточности

    #[add_in_func(name = "Test2", name_ru = "ОбработатьДанные")] 
    #[arg(Str)]
    #[arg(Str)] 
    #[returns(Str, result)] 
    read_bytes: fn(&Self, String, String) -> Result<String, Box<dyn std::error::Error>>, 
    

    }

    impl Test2 { pub fn new() -> Self { Self { connection: Arc::new(None), read_bytes: Self::read_bytes, } }

    pub fn read_bytes(&self, imya: String, telefon: String) -> Result<String, Box<dyn std::error::Error>> { 
        let k=" Взаимодействие раст и 1С работает".to_string();
        let f=imya+&telefon+&k;
        Ok(f) 
    } 
    

    }

    bug help wanted 
    opened by AleksandrSmith7 6
  • The property does not work

    The property does not work

    Hello. I added a property to the example from the repository. The function works, the property does not

    use native_api_1c::{native_api_1c_core::ffi::connection::Connection, native_api_1c_macro::AddIn};
    use std::{
        fs::{metadata, File},
        io::Read,
        sync::Arc,
    };
    
    #[derive(AddIn)]
    pub struct ByteReader {
        #[add_in_con] // соединение с 1С для вызова внешних событий
        connection: Arc<Option<&'static Connection>>, // Arc для возможности многопоточности
    
        #[add_in_func(name = "ReadBytes", name_ru = "ПрочитатьБайты")]
        #[arg(Str)]
        #[returns(Blob, result)]
        read_bytes: fn(&Self, String) -> Result<Vec<u8>, Box<dyn std::error::Error>>,
    
        #[add_in_prop(name = "TestProp", name_ru = "ТестПроп", readable, writable)]
        pub my_prop: i32,
    }
    
    impl ByteReader {
        pub fn new() -> Self {
            Self {
                connection: Arc::new(None),
                read_bytes: Self::read_bytes,
                my_prop: 230,
            }
        }
    
        pub fn read_bytes(&self, path: String) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
            let mut f = File::open(&path)?;
            let metadata = metadata(&path)?;
            let mut buffer = vec![0; metadata.len() as usize];
            f.read(&mut buffer)?;
            Ok(buffer)
        }
    }
    

    1C does not see the property and does not want to overwrite it Cleared the cache. Moved the processing to the configuration. Tried different platforms. Tried it on other PCs

    bug 
    opened by Toveal 5
  • Ошибка повторного вызова метода на русском

    Ошибка повторного вызова метода на русском

    При повторном обращении не находится метод на русском языке. Удалось исправить это поведение. Можно включить эти изменения в основную ветку?

    https://github.com/WorldException/native_api_1c_macro/commit/9b1163589f7901e26eecadead45850d28fd35eaf

    opened by WorldException 2
  • Tracking. Integration testing

    Tracking. Integration testing

    Тесты в макросе, которые просто собирают проект, хорошо проверяют работу непосредственно макроса, но этого недостаточно для проверки корректной работы готовой копмоненты. Это уже понятно, из-за того, сколько вышло ошибок со строками. Есть, как я вижу, два варианта:

    1. Тестировать с помощью OneScript, который поддерживает Native API;
    2. Сооружать какое-то тестирование с помощью непосредственно 1С.

    Мне кажется, пока что лучше 1), т.к. кроме очевидной простоты реализации в сравнении со 2м вариантом, так же проще с точки лицензирования. Потому что тестировать под "коммунити" лицензией будет больно.

    enhancement 
    opened by Sebekerga 5
  • Пустая строка не пустая (null terminator)

    Пустая строка не пустая (null terminator)

    Здравствуйте. Написал простую компоненту в качестве примера. Получаю пустую строку, проверяю в 1С на пустую строку, но она не является пустой строкой

    Код Rust:

    use std::sync::Arc;
    
    use native_api_1c::{native_api_1c_core::ffi::connection::Connection, native_api_1c_macro::AddIn};
    
    #[derive(AddIn)]
    pub struct TestStr {
        #[add_in_con]
        connection: Arc<Option<&'static Connection>>,
    
        #[add_in_func(name = "GetEmptyString", name_ru = "ПолучитьПустуюСтроку")]
        #[returns(Str)]
        pub get_empty_string: fn(&Self) -> String,
    }
    
    impl TestStr {
        pub fn new() -> Self {
            Self {
                connection: Arc::new(None),
                get_empty_string: Self::get_empty_string,
            }
        }
    
        pub fn get_empty_string(&self) -> String {
            "".to_string()
        }
    }
    

    Код 1С:

    УстановитьВнешнююКомпоненту("ОбщийМакет.Testik");
    ВК = ПодключитьВнешнююКомпоненту("ОбщийМакет.Testik", "Testik", ТипВнешнейКомпоненты.Native);
    ВК = Новый("AddIn.Testik.TestStr"); 
    	                  
    ПростоПустаяСтрока = ВК.ПолучитьПустуюСтроку();
    
    Если ПростоПустаяСтрока = "" Тогда
        Сообщить("Пустая строка реально пустая!");
    Иначе
        Сообщить("Пустая строка не пустая? Хмм");
    КонецЕсли;
    

    Используется библиотека с GitHub. Версия 0.10.5

    [dependencies]
    native_api_1c = { git = "https://github.com/Sebekerga/native_api_1c" }
    
    bug 
    opened by Toveal 9
Releases(v0.10.5)
  • v0.10.5(Sep 1, 2023)

  • v0.10.3(Aug 29, 2023)

    Fixes:

    • fixed issue where on linux
    • fixed bad behavior in Connection wrapper functions, where pointer would get dropped before sending to 1C

    Quality

    • core crate has been docs
    • general restructure of both subcrates
    Source code(tar.gz)
    Source code(zip)
  • v0.10.2(Aug 14, 2023)

    Добавлена возможность получать и возвращать типы ДвоичныеДанные и Дата в функциях

    • Date - chrono::DateTime<chrono::FixedOffset>
    • Blob - Vec<u8>
    Source code(tar.gz)
    Source code(zip)
  • v0.10.1(Aug 11, 2023)

    • Добавлены аттрибуты для определения функции:
      • arg для каждого из аргументов функции, описывает тип значения (Int, Float, Bool или String) и опциональное значение по-умолчанию
      • returns описывает возвращаемое значение и будет ли оно обвернуто в Result
      • Пример:
        #[add_in_func(name = "MyFunction", name_ru = "МояФункция")]
        #[arg(Int, default = 12)]
        #[returns(Int, result)]
        pub my_function: fn(&Self, i64) -> Result<i32, ()>
    
    • Просто улучшение кодовой базы
    Source code(tar.gz)
    Source code(zip)
Simple and portable (but not inflexible) GUI library in C that uses the native GUI technologies of each platform it supports.

libui: a portable GUI library for C This README is being written. Status It has come to my attention that I have not been particularly clear about how

Pietro Gagliardi 10.4k Dec 31, 2022
Winsafe-examples - Examples of native Windows applications written in Rust with WinSafe.

WinSafe examples This repo contains several examples of native Win32 applications written in Rust with WinSafe. All examples follow the same program s

Rodrigo 40 Dec 14, 2022
A data-first Rust-native UI design toolkit.

Druid A data-first Rust-native UI toolkit. Druid is an experimental Rust-native UI toolkit. Its main goal is to offer a polished user experience. Ther

null 8.2k Dec 31, 2022
Rust bindings to the minimalist, native, cross-platform UI toolkit `libui`

Improved User Interface A cross-platform UI toolkit for Rust based on libui iui: ui-sys: iui is a simple (about 4 kLOC of Rust), small (about 800kb, i

Rust Native UI Group 865 Dec 27, 2022
Truly cross platform, truly native. multiple backend GUI for rust

WIP: Sauron-native a rust UI library that conquers all platforms ranging from desktop to mobile devices. An attempt to create a truly native, truly cr

Jovansonlee Cesar 627 Jan 5, 2023
Cross-platform native Rust menu library

A cross-platform Rust library for managing the native operating system menus.

Mads Marquart 16 Jan 6, 2023
Native Rust library for FastCGI

The FastCGI Rust implementation. Description gfcgi is a native Rust library for FastCGI. This library supports multithreaded socket listeners and HTTP

Andrey Gridchin 9 Aug 7, 2022
Example for Rust Android Native Development

Android console application example project based on rust & cargo-xdk

Zhuo Zhang 4 Mar 17, 2022
OS-native file dialogs on Linux, OS X and Windows

nfd-rs nfd-rs is a Rust binding to the library nativefiledialog, that provides a convenient cross-platform interface to opening file dialogs on Linux,

Saurav Sachidanand 152 Nov 9, 2022
A tiny, neat C library that portably invokes native file open and save dialogs.

Native File Dialog A tiny, neat C library that portably invokes native file open, folder select and save dialogs. Write dialog code once and have it p

Michael Labbe 1.5k Dec 28, 2022
OS native dialogs for Windows, MacOS, and Linux

?? nfd2 nfd2 is a Rust binding to the nativefiledialog library, that provides a convenient cross-platform interface to opening file dialogs on Windows

Embark 33 May 15, 2022
Native Maps for Web, Mobile and Desktop

mapr Native Maps for Web, Mobile and Linux A map rendering library written in Rust. Example | Book | API | Chat in Matrix Space Project State This pro

MapLibre 942 Jan 2, 2023
Generate Anchor IDL for Native Solana Programs.

Native Solana To Anchor IDL Autogenerate Anchor IDL from programs written in Native Solana. Disclaimer The instructions must follow strict set of rule

acheron 72 Nov 10, 2022
Provides core language-agnostic functionality for LiveView Native across platforms

LiveView Native Core This repository contains an implementation of the LiveView Native core library, which is intended to handle all the details which

LiveView Native 35 Dec 27, 2022
rsautogui aims to be a cross-platform GUI automation rust crate.

rsautogui rsautogui aims to be a cross-platform GUI automation rust crate. It lets you control the mouse and keyboard to automate interactions with ot

null 5 Sep 18, 2022
A demo of using JavaScript in a Rust program, via the "deno_core" crate.

js-in-rs created by Austin Poor A demo of using JavaScript in a Rust program, via the deno_core crate. Usage js-in-rs is a sample grep-like applicatio

Austin Poor 32 Jun 12, 2023
A simple note taking application written in Rust and GTK4

Rnote A simple note taking application written in Rust and GTK4. Rnote aims to be a simple but functional note taking application for freehand drawing

Felix Zwettler 3.4k Jan 5, 2023
A simple GUI version of the pH calibration tool written in egui, based on the eframe template.

caliphui A simple GUI version of the pH calibration tool written in egui, based on the eframe template. Usage Native binaries are provided under relea

Peter Dunne 0 Dec 29, 2021
Rust docs for the Windows API

Windows API documentation for Rust This is an experimental documentation generator for the Rust for Windows project. The documentation is published he

Microsoft 52 Dec 9, 2022