.Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 14.05.16 07:42
Оценка: :)))
Начну с того, что в 1С есть технология Внешних компонент Native API Технология создания внешних компонент Технология создания внешних компонент которые работают как под Windows так и под Linux

У меня есть компонента Использование сборок .NET в 1С 7.x b 8.x. Создание внешних Компонент.

Суть которой оборачивание .Net объектов в Com объект с помощью создания класса, реализующего методы интерфейса IReflect

Но хотелось бы прикрутить этот аналог к Linux используя ВК Native API На просторах интернета нашел ссылки вызова управляемого кода из неуправляемого http://forums.dotnetfoundation.org/t/how-to-call-a-net-core-library-from-native-code-on-linux/1576/2

This C++ app allows to run custom C# method from compiled C# .dll on Linux and OS X using coreCLR

http://www.mono-project.com/docs/advanced/embedding/
Смысл идеи таков

На стороне .Net выполнять метод. Параметры сериализуются в Stream. Сначала идет тип, затем данные.

На стороне .Net Параметры десериализутся и вызывается метод InvokeMember нужного типа. При передаче ссылок на объекты их нужно обернуть и сохранить в списке и в натив передавать индекс в списке.

Так как параметры могут изменяться возвращаем как результат значения, так и параметры.

Таким образом можно загружать любые сборки вызывать любые методы.

Так как я не силен в С++ прошу направить на путь истинный или я могу помочь в интеграции натива и манагед

Исходный код обертки можно посмотреть здесь

Или скачать http://files.rsdn.ru/19608/%d0%a4%d0%b0%d0%b9%d0%bb%d1%8bNetObjectToIDispatch.zip

На ru.stackoverflow продублировал вопрос. Может кому будет интересно

http://ru.stackoverflow.com/questions/523386/%d0%92%d1%8b%d0%b7%d0%be%d0%b2-%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d1%8f%d0%b5%d0%bc%d0%be%d0%b3%d0%be-%d0%ba%d0%be%d0%b4%d0%b0-%d0%b8%d0%b7-%d0%bd%d0%b5%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d1%8f%d0%b5%d0%bc%d0%be%d0%b3%d0%be

Выложил статью Кроссплатформенное использование классов .Net из неуправляемого кода. Или аналог IDispatch на Linux
Исходники лежат Здесь


Выложил статьи
Разработка → Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux
Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux
Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux II
Асинхронное программирование в 1С через .Net Native ВК
1С,Linux,Excel,Word,OpenXML,Net Core

Исходники здесь
и солнце б утром не вставало, когда бы не было меня
Отредактировано 22.08.2016 11:12 Serginio1 . Предыдущая версия . Еще …
Отредактировано 09.08.2016 9:12 Serginio1 . Предыдущая версия .
Отредактировано 01.07.2016 10:29 Serginio1 . Предыдущая версия .
Отредактировано 01.07.2016 8:11 Serginio1 . Предыдущая версия .
Отредактировано 26.05.2016 12:00 Serginio1 . Предыдущая версия .
Отредактировано 16.05.2016 5:39 Serginio1 . Предыдущая версия .
Отредактировано 14.05.2016 19:33 Serginio1 . Предыдущая версия .
Отредактировано 14.05.2016 17:28 Serginio1 . Предыдущая версия .
Re: [Offtop] Вызов принят!
От: xobotik Россия  
Дата: 26.05.16 19:56
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Исходный код обертки можно посмотреть здесь


Напомнило: http://rsdn.ru/article/humor/select_problem.xml
Автор(ы): mrhru
Дата: 27.04.2004


А так спасибо поржал =) Особенно http://pastebin.com/x4m4D2EZ
С уважением!
Re[2]: [Offtop] Вызов принят!
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 26.05.16 21:10
Оценка:
Здравствуйте, xobotik, Вы писали:

X>Здравствуйте, Serginio1, Вы писали:


S>>Исходный код обертки можно посмотреть здесь


X>Напомнило: http://rsdn.ru/article/humor/select_problem.xml
Автор(ы): mrhru
Дата: 27.04.2004


X>А так спасибо поржал =) Особенно http://pastebin.com/x4m4D2EZ

Ты хоть поясни, что тебе напомнило, и где смеяться, и что нужно употребить?
и солнце б утром не вставало, когда бы не было меня
Отредактировано 26.05.2016 21:27 Serginio1 . Предыдущая версия .
Re: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 27.05.16 16:07
Оценка:
Здравствуйте, Serginio1, Вы писали:

Поделитесь, что смешного?
и солнце б утром не вставало, когда бы не было меня
Re[2]: .Net Core. Вызов манагед кода из натива
От: LWhisper  
Дата: 27.05.16 16:45
Оценка:
S>Поделитесь, что смешного?
Сплетающиеся в любовном экстазе русские и английские буквы, совокупляющиеся с рефлекшеном, на фоне которых забывается сам вопрос.

Если без шуток, то код очень грязный и его тяжело читать. А без понимания того что он делает, сложно что-либо советовать. Желание же ковыряться в нём пропадает с первых строк. Понимаю, что общение с 1C накладывает определенный отпечаток, но не стоит тащить из нее все самое плохое.

И, к слову, в чём заключается вопрос? Ты сам привёл ссылку на статью, чем тебя не устраивает вариант с ExecuteManagedAssembly?
Если нужен способ передачи данных, то, вероятно, это MemoryMappedFile. Если не ошибаюсь, MapFileToMem уже поддерживается. Если нет — нативные пайпы.
Re[2]: .Net Core. Вызов манагед кода из натива
От: Sharov Россия  
Дата: 27.05.16 17:24
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>Поделитесь, что смешного?


Кириллица.
Кодом людям нужно помогать!
Re[3]: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 27.05.16 17:32
Оценка:
Здравствуйте, LWhisper, Вы писали:

S>>Поделитесь, что смешного?

LW>Сплетающиеся в любовном экстазе русские и английские буквы, совокупляющиеся с рефлекшеном, на фоне которых забывается сам вопрос.

Вопрос про вызов манагед методов из нативаю

LW>Если без шуток, то код очень грязный и его тяжело читать. А без понимания того что он делает, сложно что-либо советовать. Желание же ковыряться в нём пропадает с первых строк. Понимаю, что общение с 1C накладывает определенный отпечаток, но не стоит тащить из нее все самое плохое.


То есть комментарии на русском тебя коробят? Методы на русском это сродни комментариям.
Что касается кода, то это обертка над .Net объектов, для вызова в из натива в виде Idispatch
LW>И, к слову, в чём заключается вопрос? Ты сам привёл ссылку на статью, чем тебя не устраивает вариант с ExecuteManagedAssembly?
LW>Если нужен способ передачи данных, то, вероятно, это MemoryMappedFile. Если не ошибаюсь, MapFileToMem уже поддерживается. Если нет — нативные пайпы.

Если бы ты почитал поподробнее то увидел бы, как можно сделать вызов static манагед функции из натива.
А значит можно упаковать ссылку (индекс) на объект, имя метода,параметры с типом в Stream и передавать в виде IntPtr в обе стороны.
Понятно, что со стороны натива нужно передать ссылку в манагед на метод выделения памяти.
Сам .Net так и поступает при маршалинге Com объектов. Просто в Linux нет понятия COM и это надо сделать самим.
Но выхлоп заключается в том, что на линуксе из натива можно вызвать любой .Net объект.
В Windos так и делается. Мало того есть компиляция обертки для использования событий .Net классов в нативе через обертку в COM события.
Что касается ссылок, то я в С++ не силен. Кроме того .Net Core сильно меняется с каждой бетта версией
и солнце б утром не вставало, когда бы не было меня
Re[3]: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 27.05.16 17:35
Оценка:
Здравствуйте, Sharov, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>>Здравствуйте, Serginio1, Вы писали:


S>>Поделитесь, что смешного?


S>Кириллица.

То есть русский не может писать по русски? Это же обфускация для буржуинов. А пишу то я для 1С овцев, а там все по русски. Даже операторы. Жалко, что на C# нужно переключать клавиатуру.
и солнце б утром не вставало, когда бы не было меня
Re[3]: [Offtop] Вызов принят!
От: xobotik Россия  
Дата: 30.05.16 07:10
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, xobotik, Вы писали:


X>>Здравствуйте, Serginio1, Вы писали:


S>>>Исходный код обертки можно посмотреть здесь


X>>Напомнило: http://rsdn.ru/article/humor/select_problem.xml
Автор(ы): mrhru
Дата: 27.04.2004


X>>А так спасибо поржал =) Особенно http://pastebin.com/x4m4D2EZ

S> Ты хоть поясни, что тебе напомнило, и где смеяться, и что нужно употребить?

Почитай https://msdn.microsoft.com/ru-ru/library/ff926074.aspx!
Обычно есть стандарт кодирования, которым придерживаются при разработке базовой библиотеки для какого-либо языка.
Обычно, если ты пишешь допустим на C++ и используешь Qt Framework, пишешь используя стандарт кодирования Qt Framework.
Если ты пишешь на C# и используешь .NET Framework, пишешь используя стандарт кодирования .NET Framework.
Если ты пишешь под 1C, не знаю какой там стандарт =) Но наверно какой-то есть =)
С уважением!
Re[4]: [Offtop] Вызов принят!
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 30.05.16 11:16
Оценка:
Здравствуйте, xobotik, Вы писали:

X>Здравствуйте, Serginio1, Вы писали:


S>>Здравствуйте, xobotik, Вы писали:


X>>>Здравствуйте, Serginio1, Вы писали:


S>>>>Исходный код обертки можно посмотреть здесь


X>>>Напомнило: http://rsdn.ru/article/humor/select_problem.xml
Автор(ы): mrhru
Дата: 27.04.2004


X>>>А так спасибо поржал =) Особенно http://pastebin.com/x4m4D2EZ

S>> Ты хоть поясни, что тебе напомнило, и где смеяться, и что нужно употребить?

X>Почитай https://msdn.microsoft.com/ru-ru/library/ff926074.aspx!

X>Обычно есть стандарт кодирования, которым придерживаются при разработке базовой библиотеки для какого-либо языка.
X>Обычно, если ты пишешь допустим на C++ и используешь Qt Framework, пишешь используя стандарт кодирования Qt Framework.
X>Если ты пишешь на C# и используешь .NET Framework, пишешь используя стандарт кодирования .NET Framework.
X>Если ты пишешь под 1C, не знаю какой там стандарт =) Но наверно какой-то есть =)

И чем тебе мой код смешон? Я стараюсь придерживаться приведенного тобой стандарта.
и солнце б утром не вставало, когда бы не было меня
Re[4]: .Net Core. Вызов манагед кода из натива
От: LWhisper  
Дата: 30.05.16 11:34
Оценка: 3 (1) +5
S> То есть русский не может писать по русски? Это же обфускация для буржуинов. А пишу то я для 1С овцев, а там все по русски. Даже операторы. Жалко, что на C# нужно переключать клавиатуру.
В домашнем проекте ты можешь писать так, как тебе нравится.
Локализованная 1C пошла путём Excel'я и обязывает писать на русском.
Но использовать кириллицу вместе с латиницей, доводя ситуацию до абсурда (МетодObject) — это плохая затея.
Как я уже писал, код невозможно читать. Это вовсе не отторжение к родному языку, и в комментариях он вполне имеет право на жизнь, но в таком виде это обфускация для любого программиста, сродни write-only коду.
Re[4]: .Net Core. Вызов манагед кода из натива
От: LWhisper  
Дата: 30.05.16 11:44
Оценка:
Серьёзно, друг, перечитай своё сообщение. Даже твои посты на форуме невозможно читать, не говоря уже о коде.
Это какой-то поток мыслеобразов, которые понятны лишь тебе.

S> Если бы ты почитал поподробнее то увидел бы, как можно сделать вызов static манагед функции из натива.

S>А значит можно упаковать ссылку (индекс) на объект, имя метода,параметры с типом в Stream и передавать в виде IntPtr в обе стороны.
S>Понятно, что со стороны натива нужно передать ссылку в манагед на метод выделения памяти.
S>Сам .Net так и поступает при маршалинге Com объектов. Просто в Linux нет понятия COM и это надо сделать самим.
S>Но выхлоп заключается в том, что на линуксе из натива можно вызвать любой .Net объект.
S>В Windos так и делается. Мало того есть компиляция обертки для использования событий .Net классов в нативе через обертку в COM события.
S> Что касается ссылок, то я в С++ не силен. Кроме того .Net Core сильно меняется с каждой бетта версией
Я честно пытался прочитать и предыдущий твой пост и этот. Ответа на вопрос — чем тебя не устраивает предложенное в статье решение я не нашёл.
Ты хочешь шарить .NET объекты в виде интерфейсов неявным образом, по образу и подобию COM-объектов? Зачем? Это устаревшая технология, которой на замену давно пришёл C++/CLI. В этом случае стоит посмотреть в сторону CLang, если тебе нужно направление в котором стоит копать. Или ты ищешь готовое решение из коробки? Тебе сюда: https://github.com/Marqin/simpleCoreCLRHost
Отредактировано 30.05.2016 11:47 LWhisper . Предыдущая версия .
Re[5]: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 30.05.16 11:52
Оценка:
Здравствуйте, LWhisper, Вы писали:

S>> То есть русский не может писать по русски? Это же обфускация для буржуинов. А пишу то я для 1С овцев, а там все по русски. Даже операторы. Жалко, что на C# нужно переключать клавиатуру.

LW>В домашнем проекте ты можешь писать так, как тебе нравится.
LW>Локализованная 1C пошла путём Excel'я и обязывает писать на русском.
LW>Но использовать кириллицу вместе с латиницей, доводя ситуацию до абсурда (МетодObject) — это плохая затея.
LW>Как я уже писал, код невозможно читать. Это вовсе не отторжение к родному языку, и в комментариях он вполне имеет право на жизнь, но в таком виде это обфускация для любого программиста, сродни write-only коду.
Ты плохо понимаешь по русски? То есть в комметариях имеет, а в названиях нет?
и солнце б утром не вставало, когда бы не было меня
Re[5]: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 30.05.16 11:59
Оценка:
Здравствуйте, LWhisper, Вы писали:

LW>Серьёзно, друг, перечитай своё сообщение. Даже твои посты на форуме невозможно читать, не говоря уже о коде.

LW>Это какой-то поток мыслеобразов, которые понятны лишь тебе.

S>> Если бы ты почитал поподробнее то увидел бы, как можно сделать вызов static манагед функции из натива.

S>>А значит можно упаковать ссылку (индекс) на объект, имя метода,параметры с типом в Stream и передавать в виде IntPtr в обе стороны.
S>>Понятно, что со стороны натива нужно передать ссылку в манагед на метод выделения памяти.
S>>Сам .Net так и поступает при маршалинге Com объектов. Просто в Linux нет понятия COM и это надо сделать самим.
S>>Но выхлоп заключается в том, что на линуксе из натива можно вызвать любой .Net объект.
S>>В Windos так и делается. Мало того есть компиляция обертки для использования событий .Net классов в нативе через обертку в COM события.
S>> Что касается ссылок, то я в С++ не силен. Кроме того .Net Core сильно меняется с каждой бетта версией
LW>Я честно пытался прочитать и предыдущий твой пост и этот. Ответа на вопрос — чем тебя не устраивает предложенное в статье решение я не нашёл.
LW>Ты хочешь шарить .NET объекты в виде интерфейсов неявным образом, по образу и подобию COM-объектов? Зачем? Это устаревшая технология, которой на замену давно пришёл C++/CLI. В этом случае стоит посмотреть в сторону CLang, если тебе нужно направление в котором стоит копать. Или ты ищешь готовое решение из коробки? Тебе сюда: https://github.com/Marqin/simpleCoreCLRHost
Кстати эта ссылка есть и в моих http://forums.dotnetfoundation.org/t/how-to-call-a-net-core-library-from-native-code-on-linux/1576/2
И This C++ app allows to run custom C# method from compiled C# .dll on Linux and OS X using coreCLR




1C под Win понимает только COM. И очень удобно расширять её возможности с помощью COM обертки вокруг .Net объектов.
Для кроссплатформенности введен Native ВК
Для Линукс нужно сделать аналог, с обменом данных между нативом и .Net по аналогии с IDispatch.
За ссылку спасибо. Сейчас изучаю С++. Но времени мало.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 30.05.2016 12:38 Serginio1 . Предыдущая версия . Еще …
Отредактировано 30.05.2016 12:30 Serginio1 . Предыдущая версия .
Re[5]: [Offtop] Вызов принят!
От: LWhisper  
Дата: 30.05.16 12:18
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> И чем тебе мой код смешон? Я стараюсь придерживаться приведенного тобой стандарта.

Противоречит одному из пунктов:

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


Это не потому что мы не любим русский язык, а потому что этот код тяжело читать и с ним трудно работать. C# позволяет использовать символы другого языка в идентификаторах, но делать это строго не рекомендуется. Ты сам писал про необходимость переключать язык. А у меня есть знакомый, который использует европейские умлауты в именах полей и методов. И вот как мне их вводить, с EN/RU раскладкой? А если с твоим кодом придётся работать человеку, у которого EN/FR раскладка? И это только касательно удобства. Как я писал ранее. подобная мешанина затрудняет чтение и хочется скорее закрыть документ, а не разбираться в том, что там происходит.
Re[6]: .Net Core. Вызов манагед кода из натива
От: LWhisper  
Дата: 30.05.16 12:22
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> Ты плохо понимаешь по русски? То есть в комметариях имеет, а в названиях нет?

"По-русски". Да, совершенно верно. В идентификаторах не стоит использовать символы, отличные от нижней ASCII.
Re[6]: [Offtop] Вызов принят!
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 30.05.16 12:28
Оценка:
Здравствуйте, LWhisper, Вы писали:

LW>Здравствуйте, Serginio1, Вы писали:


S>> И чем тебе мой код смешон? Я стараюсь придерживаться приведенного тобой стандарта.

LW>Противоречит одному из пунктов:
LW>

LW>Предоставление читателям возможности делать предположения, основанные на опыте, и поэтому быстрее понимать код.


LW>Это не потому что мы не любим русский язык, а потому что этот код тяжело читать и с ним трудно работать. C# позволяет использовать символы другого языка в идентификаторах, но делать это строго не рекомендуется. Ты сам писал про необходимость переключать язык. А у меня есть знакомый, который использует европейские умлауты в именах полей и методов. И вот как мне их вводить, с EN/RU раскладкой? А если с твоим кодом придётся работать человеку, у которого EN/FR раскладка? И это только касательно удобства. Как я писал ранее. подобная мешанина затрудняет чтение и хочется скорее закрыть документ, а не разбираться в том, что там происходит.


С моим кодом пока работаю только я один. А я 1С ник. И мне удобнее работать с киррилицей.
К хорошему привыкаешь быстро. Попробуй
и солнце б утром не вставало, когда бы не было меня
Re[7]: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 30.05.16 12:54
Оценка: :))
Здравствуйте, LWhisper, Вы писали:

LW>Здравствуйте, Serginio1, Вы писали:


S>> Ты плохо понимаешь по русски? То есть в комметариях имеет, а в названиях нет?

LW>"По-русски". Да, совершенно верно. В идентификаторах не стоит использовать символы, отличные от нижней ASCII.

Я пишу для 1С ников. А им методы нужны по русски. Они наоборот плюются на ASCII.
Там в большинстве по русски методы COM. Так что все должно быть в едином стиле.
Скоро и вы доживете до Юникоде
и солнце б утром не вставало, когда бы не было меня
Re: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 01.06.16 07:14
Оценка:
Здравствуйте, Serginio1, Вы писали:

Интересно, что в Microsoft Dynamics AX есть ClrObject
https://msdn.microsoft.com/en-us/library/clrobject.aspx
https://msdn.microsoft.com/en-us/library/clrobject.new.aspx

Вот пример применения

https://blogs.msdn.microsoft.com/x/2010/01/19/traversing-elements-in-an-ienumerable-from-x/

static void GenericTypeDemo(Args _args) 

{ 

    ClrObject o = new ClrObject(“System.Collections.Generic.List`1[System.Int32]”); 

    ClrObject enumerator; 

    int theValue; 


    // o is an instance of an IEnumerable<int> 

    o.Add(1); 

    o.Add(4); 

    o.Add(12); 


    print o.ToString(); 


    enumerator = o.GetEnumerator(); 


    while (enumerator.MoveNext()) 

    { 

        theValue = enumerator.get_Current(); 

        print theValue; 

    } 


    pause; 

}


Странно, что 1С сама не хочет использовать .Net в 1С
и солнце б утром не вставало, когда бы не было меня
Re: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 01.06.16 07:36
Оценка:
Здравствуйте, Serginio1, Вы писали:

С Текущей ВК к сожалению придется делать обертку на двоичных данных, что бы в них устанавливать свою структуру для того, что бы понять что это за объект. При получении такого объекта на стороне 1С нужно создать ВК обертку и передать эту структуру. Внутри уже вызывать методы используя ссылку.

При передачи в параметрах такой структуры, нужно получать ссылку и передавать уже на сторону .Net. Можно обойтись и просто ссылкой, но тогда при передаче параметров будет непонятно, что это ссылка. БинарныеДанные тоже придется упаковывать в эту структуру.

Можно конечно использовать информацию о методе, так как так или иначе нужно передавать в GetNParams количество параметров. Но в .Net есть перегрузка методов где параметр может быть и интом и объектом

Пример будет выглядеть так

 Врап=Новый("Addin.VK.WrapperNet"); 
 Список=Новый("Addin.VK.NetObject"); 

 Данные=Врап.СоздатьОбъект("System.Collections.Generic.List`1[System.String]"); 

 Список.Обернуть(Данные); 

    Для сч=1 По 10 Цикл 
       Список.Add(строка(сч));     
    КонецЦикла;


Ну и Данные можно передавать в параметрах.


В Native BK есть базовый класс с виртуальными методами

IComponentBase
bool Init(void* pConnection) 

long GetInfo() 

void Done() 

bool RegisterExtensionAs(WCHAR_T** wsLanguageExt) 

long GetNProps() 

long FindProp(const WCHAR_T* wsPropName) 

const WCHAR_T* GetPropName(long lPropNum, long lPropAlias) 

bool GetPropVal(const long lPropNum, tVariant* pvarPropVal) 

bool SetPropVal(const long lPropNum, tVariant* varPropVal) 

bool IsPropReadable(const long lPropNum) 

bool IsPropWritable(const long lPropNum) 

long GetNMethods() 

long FindMethod(const WCHAR_T* wsMethodName) 

const WCHAR_T* GetMethodName(const long lMethodNum, 
                            const long lMethodAlias) 

long GetNParams(const long lMethodNum) 


bool GetParamDefValue(const long lMethodNum, const long lParamNum, 
                          tVariant *pvarParamDefValue) 


bool HasRetVal(const long lMethodNum) 

bool CallAsProc(const long lMethodNum, 
                    tVariant* paParams, const long lSizeArray) 

bool CallAsFunc(const long lMethodNum, 
                tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray) 

void SetLocale(const WCHAR_T* loc) 


bool setMemManager(void* mem)


На самом деле нужны только
Init(void* pConnection) 

void Done() 
bool setMemManager(void* mem)

А все остальные замещает нетовский аналог

public object InvokeMember( 
    string name, 
    BindingFlags invokeAttr, 
    object[] args 
)

Где BindingFlags — перечисление отвечающее за тип вызова
(метод,чтение или установка свойства)
https://msdn.microsoft.com/ru-ru/library/system.reflection.bindingflags(v=vs.110).aspx


В pConnection можно передават ошибку в 1С
и солнце б утром не вставало, когда бы не было меня
Re: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 06.06.16 14:18
Оценка:
Здравствуйте, Serginio1, Вы писали:


Попробовал вызвать CoreCLr из натива.

создал тестовый класс
using System;
using System.Collections.Generic;
using System.Reflection;

namespace CoreClrDLL
{
    public class Program
    {
        public static object ExecuteMethod(object objOrig, string MethodName, params object[] argsOrig)
        {
            object res = null;

            Type T = objOrig.GetType();

            var list = new List<Type>();

            foreach (var obj in argsOrig)
                list.Add(obj.GetType());

            var Method = T.GetMethod(MethodName, list.ToArray());

            res = Method.Invoke(objOrig, argsOrig);

            return res;

        }


        public static int TestFunction(int i)
        {


            var rn = new Random(i);

            //   int res = rn.Next(10000);
            int res = (int)ExecuteMethod(rn, "Next", 10000);

            return res;

        }
    }
}

Пример взял отсюда http://www.fancy-development.net/hosting-net-core-clr-in-your-own-process

И соответственно вызов
typedef int (STDMETHODCALLTYPE *ManagedMethod)(int); 
HRESULT  CreateDelegate2(ICLRRuntimeHost2* pCLRRuntimeHost, DWORD appDomainID, wstring AssemblyName, wstring ClassName, wstring MethodName, INT_PTR *fnPtr) 
{ 

    HRESULT    hr = pCLRRuntimeHost->CreateDelegate( 
        appDomainID, 
        AssemblyName.c_str(), 
        ClassName.c_str(), 
        MethodName.c_str(), 
        (INT_PTR*)fnPtr); 

    return hr; 

}

И вызов
ManagedMethod pTestFunction; 

    hr = CreateDelegate2(pCLRRuntimeHost, domainId, L"CoreClrDLL", L"CoreClrDLL.Program", L"TestFunction", (INT_PTR*)&pTestFunction); 
    if (FAILED(hr)) 
    { 
        printf_s("Failed to create a delegate to the managed entry point: (%d).\n", hr); 

    } 
    else 
    printf_s("result method  pTestFunction(555) : (%d).\n", pTestFunction(555));

Нет InvokeMember придется вручную искать перегруженную функцию.

Вобщем оболочку можно сделать
и солнце б утром не вставало, когда бы не было меня
Re[2]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 07.06.16 06:57
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Нет InvokeMember придется вручную искать перегруженную функцию.


S>Вобщем оболочку можно сделать


InvokeMember брал на себя поиск нужного метода и передачу параметров params.
И соответственно встал вопрос как искать подходящий метод.
1. Когда один из параметров null
Каков приоритет типов?
2. Кода есть params
Сначала идут методы с большим количеством параметров?
и солнце б утром не вставало, когда бы не было меня
Re[3]: Приоритет вызова перегруженных методов
От: Sinix  
Дата: 07.06.16 11:04
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> InvokeMember брал на себя поиск нужного метода и передачу параметров params.

S>И соответственно встал вопрос как искать подходящий метод.

Для начала лучше перетащить разруливание перегрузок в managed-код. Дальше проще и зависит от задачи.

Подобрать перегрузку, зная типы аргументов? type.GetMethod("name", bindingFlags, argTypes) или как-то так.

Известны только значения? Пишем вызов любого метода через dynamic, с помошью декомпилятора смотрим что за код генерится под капотом, повторяем вручную. Ключевые слова для поиска — CallSite<T>, CallSiteBinder.

Первое попавшееся: https://habrahabr.ru/post/144330/
Re[4]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 07.06.16 11:27
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>> InvokeMember брал на себя поиск нужного метода и передачу параметров params.

S>>И соответственно встал вопрос как искать подходящий метод.

S>Для начала лучше перетащить разруливание перегрузок в managed-код. Дальше проще и зависит от задачи.


S>Подобрать перегрузку, зная типы аргументов? type.GetMethod("name", bindingFlags, argTypes) или как-то так.


S>Известны только значения? Пишем вызов любого метода через dynamic, с помошью декомпилятора смотрим что за код генерится под капотом, повторяем вручную. Ключевые слова для поиска — CallSite<T>, CallSiteBinder.


S>Первое попавшееся: https://habrahabr.ru/post/144330/


Я хочу сделать по аналогии с Использование сборок .NET в 1С 7.x b 8.x.

То есть использование любых сборок из Натива. Например http://ru.stackoverflow.com/questions/532477/%d0%9f%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b0-%d0%bf%d0%be%d0%b4%d0%bf%d0%b8%d1%81%d0%b8-%d0%ad%d0%a6%d0%9f-%d0%b2-%d1%84%d0%b0%d0%b9%d0%bb%d0%b5-online-%d0%bf%d1%80%d0%be%d0%b2%d0%b5%d1%80%d0%ba%d0%b0-%d1%81%d0%b5%d1%80%d1%82%d0%b8%d1%84%d0%b8%d0%ba%d0%b0%d1%82%d0%b0-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d1%8f-c-%d1%87%d0%b5%d1%80%d0%b5%d0%b7-%d0%b1%d0%b8%d0%b1

Это все прекрасно работает в Win через COM и InvokeMember. Но есть желание перенести это все на Линукс.
Соответственно я не знаю, что и как будет вызываться, но динамически я должен найти самый подходящий перегруженный метод.

Например есть две функции

void Метод(int парам, string str)
 void Метод(int парам, object str)

При вызове Метод(1,null) какой метод выбрать?

С параметрами массивами
void Метод(int парам, params object[] str)
void Метод(int парам,int пара2, object str)

Метод(1,1,6)

Кстати в Core .Net много отличий. Например во взрослом
public abstract object[] GetCustomAttributes(
    Type attributeType,
    bool inherit
)


То в Core все через расширения
public static IEnumerable<Attribute> GetCustomAttributes(this ParameterInfo element, Type attributeType, bool inherit);


Так на просторах нашел


public static object call(MethodInfo Method, object Target, params object[] input)
        {

   
            ParameterInfo[] parameters = Method.GetParameters();
            bool hasParams = false;
            if (parameters.Length > 0)
                hasParams = parameters[parameters.Length - 1].GetCustomAttributes(typeof(ParamArrayAttribute), false).GetEnumerator().MoveNext();

            if (hasParams)
            {
                int lastParamPosition = parameters.Length - 1;

                object[] realParams = new object[parameters.Length];
                for (int i = 0; i < lastParamPosition; i++)
                    realParams[i] = input[i];

                Type paramsType = parameters[lastParamPosition].ParameterType.GetElementType();
                Array extra = Array.CreateInstance(paramsType, input.Length - lastParamPosition);
                for (int i = 0; i < extra.Length; i++)
                    extra.SetValue(input[i + lastParamPosition], i);

                realParams[lastParamPosition] = extra;

                input = realParams;
            }

            return Method.Invoke(Target, input);
        }


Но нужно смотреть на Out и Ref параметры.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 07.06.2016 12:51 Serginio1 . Предыдущая версия .
Re[5]: Приоритет вызова перегруженных методов
От: Sinix  
Дата: 07.06.16 13:32
Оценка: 12 (1)
Здравствуйте, Serginio1, Вы писали:


S> Я хочу сделать по аналогии с Использование сборок .NET в 1С 7.x b 8.x.

А тут не имеет значения, что вы хотите. Важно только то, что поддерживается, т.е. C-style ABIs. Зачатки COM Interop есть, но только под win.
Нужно что-то более изощрённое — придётся изобретать магию самому, что требует досконального знания как нативной части, так и кишков маршаллинга CoreCLR. Я, к примеру, за это не возьмусь, т.к. только на поверхностное изучение минимум пару недель придётся потратить.


S> То есть использование любых сборок из Натива.

В общем случае нереально. Не, если ограничиться структурами / делегатами и следить за временем жизни ссылок, то что-то может и получиться, но на "любых сборок" я бы не рассчитывал. Вам точно не достаточно того, что есть в оф.справке, секция "Invoking managed code from unmanaged code"?

Если что, даже менее амбициозные замашки на c++ выглядят как-то так.

S> Это все прекрасно работает в Win через COM и InvokeMember. Но есть желание перенести это все на Линукс.

Нельзя просто так взять и перенести COM на платформу, которая его не поддерживает. Ваш кэп


S>При вызове Метод(1,null) какой метод выбрать?

Простой способ: AmbigiousMatchException
Сложный способ — подрубаем DLR, как советовал выше

S>То в Core все через расширения

Core как такового нет. Есть RC, которое, как ВНЕЗАПНО выяснилось, несовместимо с 99% существующего кода и невнятные обещания binary compatibility для основных классов BCL, включая reflection.

Я бы не заморачивался с как минимум до следующего релиза. Если конечно нет желания оседлать хайп и снять все сливки Риски соответствующие.
Re[6]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 07.06.16 14:35
Оценка: 21 (1)
Здравствуйте, Sinix, Вы писали:

S> Здравствуйте, Serginio1, Вы писали:



S>> Я хочу сделать по аналогии с Использование сборок .NET в 1С 7.x b 8.x.

S>А тут не имеет значения, что вы хотите. Важно только то, что поддерживается, т.е. C-style ABIs. Зачатки COM Interop есть, но только под win.
S>Нужно что-то более изощрённое — придётся изобретать магию самому, что требует досконального знания как нативной части, так и кишков маршаллинга CoreCLR. Я, к примеру, за это не возьмусь, т.к. только на поверхностное изучение минимум пару недель придётся потратить.


S>> То есть использование любых сборок из Натива.

S>В общем случае нереально. Не, если ограничиться структурами / делегатами и следить за временем жизни ссылок, то что-то может и получиться, но на "любых сборок" я бы не рассчитывал. Вам точно не достаточно того, что есть в оф.справке, секция "Invoking managed code from unmanaged code"?

Реально. Кратко. Объекты хранятся в массивах. Передаются индексы в массивах. На стороне 1С есть метод
bool CAddInNative::CallAsFunc(const long lMethodNum,
                tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray)
{ 
    return false; 
}


Через IntPtr зная структуры я могу распаковать параметры (Marshal)в том числе и индексы на Объекты. А память для строк byte[] я могу на стороне .Net получив ссылку на метод.
Могу просто все запаковывать в масив.
Меня сейчас просто волнуют приоритеты перегруженных методов. Но могу не заморачиваться пока и выбирать подходящий метод



S>Если что, даже менее амбициозные замашки на c++ выглядят как-то так.


S>> Это все прекрасно работает в Win через COM и InvokeMember. Но есть желание перенести это все на Линукс.

S>Нельзя просто так взять и перенести COM на платформу, которая его не поддерживает. Ваш кэп

Был такой компонет TSocketConnection в Delphi. Суть его в том, что это была замена DCOM. Дам используя IDispatch данные упаковывались в массив. Ссылки на объекты на стороне сервера упаковывались в Idispatch и маршалились обратно. Все это реализуема на уровне собственного маршалинга.

S>>При вызове Метод(1,null) какой метод выбрать?

S>Простой способ: AmbigiousMatchException
S>Сложный способ — подрубаем DLR, как советовал выше
DLR не подходит. Я не знаю заранее, что вызовется. В DLR уже известна сигнатура.

S>>То в Core все через расширения

S>Core как такового нет. Есть RC, которое, как ВНЕЗАПНО выяснилось, несовместимо с 99% существующего кода и невнятные обещания binary compatibility для основных классов BCL, включая reflection.
Ну Method.Invoke(); и


Type T = typeof(string);

var Method = T.GetMethod("Format",new Type[]{ T,  typeof(Object[])});


Работают.
S>Я бы не заморачивался с как минимум до следующего релиза. Если конечно нет желания оседлать хайп и снять все сливки Риски соответствующие.

Ну мне еще C++ нужно изучить, а заодно напишу аналог InvokeMember
и солнце б утром не вставало, когда бы не было меня
Re[7]: Приоритет вызова перегруженных методов
От: Sinix  
Дата: 07.06.16 14:48
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>>> То есть использование любых сборок из Натива.

S>>В общем случае нереально.
S> Реально. Кратко. Объекты хранятся в массивах. Передаются индексы в массивах. На стороне 1С есть метод

Оно будет работать или для вызовов managed->native, или для случаев, когда объекты живут не дольше, чем время вызова native->managed. Иначе получаем или утечку объектов на managed-стороне, или порчу памяти из-за пожраного GC объекта, или адскую магию с рефкаунтингом (по, сути, переизобретение IUnknown).

Довольно существенное ограничение.

Если устраивает — всё сводится к получить на managed-стороне массив объектов-параметров + тип + имя метода. Дальше всё как в первом ответе написал, второй вариант.

S> DLR не подходит. Я не знаю заранее, что вызовется. В DLR уже известна сигнатура.

Вообще-то неизвестна, в рантайме определяется. Достаточно только набора значений.
Re[8]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 07.06.16 15:06
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>>>> То есть использование любых сборок из Натива.

S>>>В общем случае нереально.
S>> Реально. Кратко. Объекты хранятся в массивах. Передаются индексы в массивах. На стороне 1С есть метод

S>Оно будет работать или для вызовов managed->native, или для случаев, когда объекты живут не дольше, чем время вызова native->managed. Иначе получаем или утечку объектов на managed-стороне, или порчу памяти из-за пожраного GC объекта, или адскую магию с рефкаунтингом (по, сути, переизобретение IUnknown).


Не читаешь ты. Прежде чем отправить в натив объект сохраняется в статическом массиве массиве. Жить он будет пока его из массива не удалят.

На стороне 1С есть подсчет ссылок и Done() при разрушении объекта, которое я могу ипользовать для удаления из массива.

Кроме того можно освобождать все ссылки при разрушении домена

pCLRRuntimeHost->UnloadAppDomain(domainId, true);

    // Stop the runtime host
    pCLRRuntimeHost->Stop();


S>Довольно существенное ограничение.


S>Если устраивает — всё сводится к получить на managed-стороне массив объектов-параметров + тип + имя метода. Дальше всё как в первом ответе написал, второй вариант.


S>> DLR не подходит. Я не знаю заранее, что вызовется. В DLR уже известна сигнатура.

S>Вообще-то неизвестна, в рантайме определяется. Достаточно только набора значений.

DLR то как раз статический. Но он мне все равно нужен для использования DynamicObject

Кстати попробовал на стороне Манагед


public static int TestFunctionIntPtr(IntPtr i)
        {


            
            int res = Marshal.ReadInt32(i);

            return res;

        }



И вызов

typedef int (STDMETHODCALLTYPE *ManagedMethodIntPtr)(int*);

ManagedMethodIntPtr pTestFunctionIntPtr;
    //TestFunctionIntPtr

    hr = CreateDelegate2(pCLRRuntimeHost, domainId, L"CoreClrDLL", L"CoreClrDLL.Program", L"TestFunctionIntPtr", (INT_PTR*)&pTestFunctionIntPtr);
    if (FAILED(hr))
    {
        printf_s("Failed to create a delegate to the managed entry point: (%d).\n", hr);

    }
    else
    {
        cout << "Press Key";
        cin.get();
        int i = 555;
        printf_s("result method  pTestFunctionIntPtr(555) : (%d).\n", pTestFunctionIntPtr(&i));
    }


Marshal такой же как и во взрослом. А значит могу ползать по памяти как хочу.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 07.06.2016 15:09 Serginio1 . Предыдущая версия .
Re[8]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 07.06.16 18:22
Оценка: :)
Здравствуйте, Sinix, Вы писали:



S>> DLR не подходит. Я не знаю заранее, что вызовется. В DLR уже известна сигнатура.

S>Вообще-то неизвестна, в рантайме определяется. Достаточно только набора значений.
Ну самом деле в DLR строится дерево и компилится. Это нормально, когда известны методы, сигнатура они известны на этапе компиляции.
А вот в моем случае вообще ничего неизвестно.
Но это не большая беда, так как я могу получить используемые типы. Просто нужны правила для приоритетов.
То есть методы я могу отсортировать по признаку есть params или нет, ну и по количеству параметров.
Сначала отбираются без params, если не находятся, то выбираются от большего к меньшему с params.

А, что касается null, то случайным образом из доступных ссылочных типов или Nullable
и солнце б утром не вставало, когда бы не было меня
Re[9]: Приоритет вызова перегруженных методов
От: Sinix  
Дата: 08.06.16 06:16
Оценка: 15 (2) +1
Здравствуйте, Serginio1, Вы писали:

S> Не читаешь ты. Прежде чем отправить в натив объект сохраняется в статическом массиве массиве. Жить он будет пока его из массива не удалят.

Ну, т.е. как и говорил, получаем или утечку объектов на managed-стороне, или адскую магию с рефкаунтингом (по, сути, переизобретение IUnknown).
Для сложных графов с изменяемыми свойствами-объектами тесты как минимум надо сделать

S>>Вообще-то неизвестна, в рантайме определяется. Достаточно только набора значений.

S> DLR то как раз статический. Но он мне все равно нужен для использования DynamicObject

Вот народ я с вас фигею. Вам дают карту с сокровищами, а вы требуете чтоб вас экспрессом минуя все три тома приключений доставили прямо в термал спа "Золотое кольцо" (магнитик на холодильник с Балрогом в подарок). Где ваша это... мазохизм? Стремление усложнить жизнь? Граблефилия? А, авантюризм, во!

Держите, скучный вы человек:
        private static CallSite<Action<CallSite, Type, object, object>> callSite;

        static void Main(string[] args)
        {
            CallADynamic(1, 2);
            CallADynamic(null, null);
            CallADynamic(null, new object());
        }

        private static void CallADynamic(params object[] data)
        {
            if (callSite == null)
            {
                callSite =
                    CallSite<Action<CallSite, Type, object, object>>.Create(
                        Binder.InvokeMember(
                            CSharpBinderFlags.ResultDiscarded,
                            "CallA", null, typeof(Program), new CSharpArgumentInfo[]
                            {
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null),
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
                            }));
            }
            callSite.Target(callSite, typeof(Program), data[0], data[1]);
        }

        static void CallA(params int[] args)
        {
            Console.WriteLine("params");
        }

        static void CallA(object a, object b)
        {
            Console.WriteLine("objects");
        }

        static void CallA(object a, string b)
        {
            Console.WriteLine("object+string");
        }


Как допилить до вызова произвольного метода — сами-сами. Иначе вообще никакого удовольствия не будет.

  P.S.
Re[10]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.06.16 06:51
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>> Не читаешь ты. Прежде чем отправить в натив объект сохраняется в статическом массиве массиве. Жить он будет пока его из массива не удалят.

S>Ну, т.е. как и говорил, получаем или утечку объектов на managed-стороне, или адскую магию с рефкаунтингом (по, сути, переизобретение IUnknown).
S>Для сложных графов с изменяемыми свойствами-объектами тесты как минимум надо сделать

Опять не читаешь. На стороне 1С есть подсчет ссылок и Done при разрушении.
Кроме того могу выгрузить домен.

S>>>Вообще-то неизвестна, в рантайме определяется. Достаточно только набора значений.

S>> DLR то как раз статический. Но он мне все равно нужен для использования DynamicObject

S>Вот народ я с вас фигею. Вам дают карту с сокровищами, а вы требуете чтоб вас экспрессом минуя все три тома приключений доставили прямо в термал спа "Золотое кольцо" (магнитик на холодильник с Балрогом в подарок). Где ваша это... мазохизм? Стремление усложнить жизнь? Граблефилия? А, авантюризм, во!


S>Держите, скучный вы человек:

S>
S>        private static CallSite<Action<CallSite, Type, object, object>> callSite;

S>        static void Main(string[] args)
S>        {
S>            CallADynamic(1, 2);
S>            CallADynamic(null, null);
S>            CallADynamic(null, new object());
S>        }

S>        private static void CallADynamic(params object[] data)
S>        {
S>            if (callSite == null)
S>            {
S>                callSite =
S>                    CallSite<Action<CallSite, Type, object, object>>.Create(
S>                        Binder.InvokeMember(
S>                            CSharpBinderFlags.ResultDiscarded,
S>                            "CallA", null, typeof(Program), new CSharpArgumentInfo[]
S>                            {
S>                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null),
S>                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
S>                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
S>                            }));
S>            }
S>            callSite.Target(callSite, typeof(Program), data[0], data[1]);
S>        }

S>        static void CallA(params int[] args)
S>        {
S>            Console.WriteLine("params");
S>        }

S>        static void CallA(object a, object b)
S>        {
S>            Console.WriteLine("objects");
S>        }

S>        static void CallA(object a, string b)
S>        {
S>            Console.WriteLine("object+string");
S>        }
S>


S>Как допилить до вызова произвольного метода — сами-сами. Иначе вообще никакого удовольствия не будет.


S>
  P.S.


Спасибо! Веселый Вы наш. Но возникают вопросы.

Я так понимаю, что можно создать Кучу CallSite<Action<CallSite, Type, object, object>>
По количеству аргументов и использовать их?
И получается для каждого вызова я должен создавать свой callSite по имени метода, типу и количеству агрументов.
Сейчас проверю кстати код на CoreClr.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 08.06.2016 7:28 Serginio1 . Предыдущая версия . Еще …
Отредактировано 08.06.2016 7:07 Serginio1 . Предыдущая версия .
Re[11]: Приоритет вызова перегруженных методов
От: Sinix  
Дата: 08.06.16 07:13
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>1. CallSite под определенную сигнатуру (CallSite<Action<CallSite, Type, object, object>> )

Угу. Но нагенерить конечное количество не проблема как бы, достаточно прошвырнуться по GetMethods().

S>2. Как определить с params (удобно передавать без массива)

Не, ну до такой степени лениться — это уже перебор Первый вызов в примере.

S>3. Каково время на компиляцию если для каждого вызова нужно создавать CallSite?

Хитрый план:
1. Взять штуку, которая используется под капотом IronPython/IronRuby/прочих динамических языков под CLR.
2. Подозревать, что оно может тормозить.


Не для каждого, а для первого. CallSite кэширует сгенеренные делегаты.


S> Пока это мало чем отличается от T.GetMethod(имяМетода,Type[] типы);

Не вопрос, как сделаете корректное разруливание перегрузок по значениям аргументов в GetMethod() — так сразу и приходите.

P.S. И чистите при ответе оверквотинг Глаза же вылазят.
Re[12]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.06.16 07:38
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>>1. CallSite под определенную сигнатуру (CallSite<Action<CallSite, Type, object, object>> )

S>Угу. Но нагенерить конечное количество не проблема как бы, достаточно прошвырнуться по GetMethods().
У меня обертка не для одного типа, а для вех возможных типов, о которых я не знаю на этапе компиляции.
В DLR уже заранее известно и имя метода и количество параметров.
Для моего подхода это не совсем удобно, хотя конечно можно и поизвращаться.
Но по моему проще самому написать поиск нужного метода. Это не сложно. Логика приоритеты мне понятны.
Кстати возможно, что при вызове GetMethods они идут уже в приоритетно порядке. Посмотрю.



S>>2. Как определить с params (удобно передавать без массива)


S>Не, ну до такой степени лениться — это уже перебор Первый вызов в примере.

Прошу прощения. Я уже подправил ответ.

S>>3. Каково время на компиляцию если для каждого вызова нужно создавать CallSite?

S>Хитрый план:
S>1. Взять штуку, которая используется под капотом IronPython/IronRuby/прочих динамических языков под CLR.
S>2. Подозревать, что оно может тормозить.
S>

S>Не для каждого, а для первого. CallSite кэширует сгенеренные делегаты.

Ну у меня то может быть всего один раз.


S>> Пока это мало чем отличается от T.GetMethod(имяМетода,Type[] типы);

S>Не вопрос, как сделаете корректное разруливание перегрузок по значениям аргументов в GetMethod() — так сразу и приходите.
Да там не так и сложно. Если GetMethods() выдает по приоритету.

S>P.S. И чистите при ответе оверквотинг Глаза же вылазят.

Ок.
и солнце б утром не вставало, когда бы не было меня
Re[10]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.06.16 07:56
Оценка:
Здравствуйте, Sinix, Вы писали:

Проверил на CoreNet. Работает

params
object+string
objects
и солнце б утром не вставало, когда бы не было меня
Re[13]: Приоритет вызова перегруженных методов
От: Sinix  
Дата: 08.06.16 07:57
Оценка: +2
Здравствуйте, Serginio1, Вы писали:

S>>Угу. Но нагенерить конечное количество не проблема как бы, достаточно прошвырнуться по GetMethods().

S> У меня обертка не для одного типа, а для вех возможных типов, о которых я не знаю на этапе компиляции.
В рантайме нагенерить. Ну блин, не заставляйте меня совсем всё разжёвывать, так неинтересно.


S>В DLR уже заранее известно и имя метода и количество параметров.

S> Для моего подхода это не совсем удобно, хотя конечно можно и поизвращаться.
S>Но по моему проще самому написать поиск нужного метода. Это не сложно. Логика приоритеты мне понятны.

Магия с корректным разруливанием перегрузок включая вывод генерик-параметров и implicit conversions — одна из сложнейших частей шарпа.

Оптимизм это конечно хорошо, но только при условии, что человек ориентируется в матчасти.
Иначе получается что-то в духе "хочу сделать свою СУБД. Логика и приоритеты понятны, так что проблем не будет."
Оно с одной стороны забавно, с другой — представляешь, сколько времени будет убито впустую чисто из-за нежелания разобраться в вопросе и уже не смешно.
Re[14]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.06.16 08:35
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>>>Угу. Но нагенерить конечное количество не проблема как бы, достаточно прошвырнуться по GetMethods().

S>> У меня обертка не для одного типа, а для вех возможных типов, о которых я не знаю на этапе компиляции.
S>В рантайме нагенерить. Ну блин, не заставляйте меня совсем всё разжёвывать, так неинтересно.
Это я понимаю. Вопрос что выгоднее сделать универсальный поиск метода или генерить в рантайме калсайты.

S>>В DLR уже заранее известно и имя метода и количество параметров.

S>> Для моего подхода это не совсем удобно, хотя конечно можно и поизвращаться.
S>>Но по моему проще самому написать поиск нужного метода. Это не сложно. Логика приоритеты мне понятны.

S>Магия с корректным разруливанием перегрузок включая вывод генерик-параметров и implicit conversions — одна из сложнейших частей шарпа.

Согласен. Но она существует.

S>Оптимизм это конечно хорошо, но только при условии, что человек ориентируется в матчасти.

S>Иначе получается что-то в духе "хочу сделать свою СУБД. Логика и приоритеты понятны, так что проблем не будет."
S>Оно с одной стороны забавно, с другой — представляешь, сколько времени будет убито впустую чисто из-за нежелания разобраться в вопросе и уже не смешно.
Но и твое предложение не совсем удобно. Практический на каждый вызов я должен создавать привязку.
Хотя можно ограничится и 16 параметрами. Надо посмотреть на производительность и для каждого типа кэшировать методы по имени метода и количеству параметров.
Спасибо!
и солнце б утром не вставало, когда бы не было меня
Re[14]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.06.16 09:40
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>>>Угу. Но нагенерить конечное количество не проблема как бы, достаточно прошвырнуться по GetMethods().

S>> У меня обертка не для одного типа, а для вех возможных типов, о которых я не знаю на этапе компиляции.
S>В рантайме нагенерить. Ну блин, не заставляйте меня совсем всё разжёвывать, так неинтересно.

Значит я могу нагенерировать методы

public static CallSite<Func<CallSite, Type, object, object, object>>  CallADynamic2Params(string MethodName)
        {
            
             var   res =
                    CallSite<Func<CallSite, Type, object, object, object>>.Create(
                        Binder.InvokeMember(
                            CSharpBinderFlags.ResultDiscarded,
                            MethodName,null, typeof(Program),  new CSharpArgumentInfo[]
                            {
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType | CSharpArgumentInfoFlags.IsStaticType, null),
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                                CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
                            }));

            return res;
        }

        public static object CallFor2Param(Type type, object DynamicCalSite, params object[] data)
        {
            var cS = (CallSite<Func<CallSite, Type, object, object, object>>)DynamicCalSite;
            return cS.Target(cS, type, data[0], data[1]);


        }



Сохранять CallSite для типа по имени и количеству параметров.

и вызывать


var callSite = DynamicCall.CallADynamic2Params("CallA");

            DynamicCall.CallFor2Param(typeof(DynamicCall),callSite,1, 2);
            DynamicCall.CallFor2Param(typeof(DynamicCall), callSite, null, null);
            DynamicCall.CallFor2Param(typeof(DynamicCall), callSite, null, new object());

            double d = 78;
            var obj1 = DynamicCall.CallFor2Param(typeof(DynamicCall), callSite, 1, d);



А можно еще нескромный вопрос.
Это для статических методов. А как для объектов?
и солнце б утром не вставало, когда бы не было меня
Re[15]: Приоритет вызова перегруженных методов
От: Sinix  
Дата: 08.06.16 09:45
Оценка: 18 (2) +1
Здравствуйте, Serginio1, Вы писали:

S> Это я понимаю. Вопрос что выгоднее сделать универсальный поиск метода или генерить в рантайме калсайты.

Вопрос из серии "сделать универсальный транслятор sql-запросов или просто подключить EF?"


S>>Магия с корректным разруливанием перегрузок включая вывод генерик-параметров и implicit conversions — одна из сложнейших частей шарпа.

S> Согласен. Но она существует.
Это не значит, что её легко повторить


S> Но и твое предложение не совсем удобно. Практический на каждый вызов я должен создавать привязку.


"И конфеты за меня есть будете? — Ага!". Ну и далее по тексту. Раз сами просите — вот вам: убийца -- садовник. Эхх, такую интригу убили...
Отредактировано 08.06.2016 9:48 Sinix . Предыдущая версия .
Re[16]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.06.16 10:01
Оценка:
Здравствуйте, Sinix, Вы писали:


S>"И конфеты за меня есть будете? — Ага!". Ну и далее по тексту. Раз сами просите — вот вам: убийца -- садовник. Эхх, такую интригу убили...


Вот уж наиогромнейшее спасибо!
Пошел проверять после обеда.
и солнце б утром не вставало, когда бы не было меня
Re[10]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.06.16 11:02
Оценка:
Здравствуйте, Sinix, Вы писали:

Есть проблема с ref

Сделать такой метод
static public int CallA(ref int a, double b)
        {
            a = 9;
            SB.AppendLine("ref int+double");
            return 9;
        }


То он невидим. Если добавить |CSharpArgumentInfoFlags.IsRef
Cannot convert type 'object' to 'ref int'
и солнце б утром не вставало, когда бы не было меня
Re[11]: Приоритет вызова перегруженных методов
От: Sinix  
Дата: 08.06.16 11:22
Оценка: 3 (1)
Здравствуйте, Serginio1, Вы писали:


S>То он невидим. Если добавить |CSharpArgumentInfoFlags.IsRef

S>Cannot convert type 'object' to 'ref int'
Угу, есть такой нюанс.

Способы обойти разнообразные, навскидку —
https://github.com/ekonbenefits/dynamitey/wiki/UsageReallyLateBinding#really-late-binding-arguments-with-refout-arguments-etc
и
http://stackoverflow.com/questions/3146317/create-expression-to-invoke-method-with-out-parameter

Дальше лучше в issues dynamitey спрашивать.
Re[12]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.06.16 11:48
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:



S>>То он невидим. Если добавить |CSharpArgumentInfoFlags.IsRef

S>>Cannot convert type 'object' to 'ref int'
S>Угу, есть такой нюанс.

S>Способы обойти разнообразные, навскидку —

S>https://github.com/ekonbenefits/dynamitey/wiki/UsageReallyLateBinding#really-late-binding-arguments-with-refout-arguments-etc
S>и
S>http://stackoverflow.com/questions/3146317/create-expression-to-invoke-method-with-out-parameter

S>Дальше лучше в issues dynamitey спрашивать.


К сожалению Dynamitey он не для Core.
А второе нужно найти это MethodInfo.
Можно пока плюнуть на ref. Главное показать рабочий вариант.
Спасибо!
и солнце б утром не вставало, когда бы не было меня
Re[12]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.06.16 13:10
Оценка:
Здравствуйте, Sinix, Вы писали:

Попробую я сортировку с компарером


 public class MyComparer : IComparer<Type>
    {

        public int Compare(Type TypeA, Type TypeB)
        {
            if (TypeA.IsAssignableFrom(TypeB)) return 1;

            if (TypeB.IsAssignableFrom(TypeA)) return -1;

            if (TypeA.IsByRef) return -1;

            if (TypeB.IsByRef) return  1;

            return 0;
        }

    }



Сортировка типов получается такая.

var Comp = new MyComparer();
var tt = (new Type[] { typeof(int), typeof(int).MakeByRefType(),  typeof(double), typeof(object), typeof(string) }).OrderBy(t=>t, Comp).ToArray();


+ [0] {Name = "Int32&" FullName = "System.Int32&"} System.Type {System.RuntimeType}
+ [1] {Name = "Int32" FullName = "System.Int32"} System.Type {System.RuntimeType}
+ [2] {Name = "Double" FullName = "System.Double"} System.Type {System.RuntimeType}
+ [3] {Name = "String" FullName = "System.String"} System.Type {System.RuntimeType}
+ [4] {Name = "Object" FullName = "System.Object"} System.Type {System.RuntimeType}




var Method = typeof(DynamicCall).GetMethod("CallA", new Type[] { typeof(int).MakeByRefType(), typeof(double) });

            object[] парам= new object[] { i,d};
            res = Method.Invoke(null, парам);


Изменяет первый элемент массива.


Можно сортировать как 1000- уровень иерархии от Object
и солнце б утром не вставало, когда бы не было меня
Отредактировано 08.06.2016 15:14 Serginio1 . Предыдущая версия .
Re[12]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.06.16 14:30
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:



S>>То он невидим. Если добавить |CSharpArgumentInfoFlags.IsRef

S>>Cannot convert type 'object' to 'ref int'
S>Угу, есть такой нюанс.

S>Способы обойти разнообразные, навскидку —

S>https://github.com/ekonbenefits/dynamitey/wiki/UsageReallyLateBinding#really-late-binding-arguments-with-refout-arguments-etc
S>и
S>http://stackoverflow.com/questions/3146317/create-expression-to-invoke-method-with-out-parameter

S>Дальше лучше в issues dynamitey спрашивать.


Кстати решил посмотреть что выдает GetMethod с параметрами без сигнатуры

так вызов
typeof(DynamicCall).GetMethod("CallA", new Type[] { typeof(int), typeof(int) })



{Int32 CallA(Int32, Double)}

На
typeof(DynamicCall).GetMethod("CallA", new Type[] { typeof(int), typeof(string) })
ругается
А на
typeof(DynamicCall).GetMethod("CallA", new Type[] { typeof(object), typeof(string) })

все нормально.
Да уж.
и солнце б утром не вставало, когда бы не было меня
Re[12]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 09.06.16 07:13
Оценка:
Здравствуйте, Sinix, Вы писали:
S>Не вопрос, как сделаете корректное разруливание перегрузок по значениям аргументов в GetMethod() — так сразу и приходите.

Идея такая создаем класс для сравнения

namespace CoreClrDLL
{

   

    public class ИнформацияОТипе: IComparable<ИнформацияОТипе>
    {
        public Type Тип;
        bool IsByRef;
        bool IsValue;
        int УровеньИерархии;
        bool IsNullable;
        public ИнформацияОТипе(Type type)
        {
            var TI = type.GetTypeInfo();
            IsByRef = TI.IsByRef;

           

            if (IsByRef)
            {
                Тип = type.GetElementType();
                TI = Тип.GetTypeInfo();
                
            }
            else
                Тип = type;


            IsValue = TI.IsValueType;

            if (IsValue)
            {
                УровеньИерархии = 0;
                if (TI.IsGenericType && TI.GetGenericTypeDefinition() == typeof(Nullable<>))
                {
                    IsNullable = true;

                    Тип = TI.GenericTypeArguments[0];
                }

            }
            else
                УровеньИерархии = НайтиУровень(0, Тип);


        }

        static int НайтиУровень(int Уровень, Type type)
        {

            if (type == typeof(object))
                return Уровень;

            return НайтиУровень(Уровень + 1, type.GetTypeInfo().BaseType);

        }

       
        public  int CompareTo(ИнформацияОТипе elem)
        {
           

            int res = -IsByRef.CompareTo(elem.IsByRef);

            if (res != 0) return res;

            if (Тип == elem.Тип)
                return 0;

            res = -IsValue.CompareTo(elem.IsValue);

            if (res != 0) return res;


            if (IsValue && elem.IsValue)
            {
                res = IsNullable.CompareTo(elem.IsNullable);

                if (res != 0) return res;

            }

            res = -УровеньИерархии.CompareTo(elem.УровеньИерархии);

            if (res != 0) return res;

           

            return Тип.ToString().CompareTo(elem.Тип.ToString());
        }

        public bool Равняется(Type type)
        {

            if (type==null)
            {
                if (!IsValue)
                    return true;

                if (IsNullable)
                    return true;
                else
                    return false;

            }

            // или использовать IsInstanceOfType
            if (IsValue) return Тип == type;

                return Тип.IsAssignableFrom(type);

        }
    }


    

    public class ИнфoрмацияОМетоде<T>  where T : MethodBase
    {
        public T Method;
        public ИнформацияОТипе[] Параметры;
        public int КоличествоПараметров;
        public bool hasParams;
        public Type TypeParams;
        public int КоличествоПараметровПарамс;
        public ИнформацияОТипе ИнформацияОТипеЭлемента;

        public static Dictionary<Type, ИнформацияОТипе> ИнформацияПоТипу = new Dictionary<Type, ИнформацияОТипе>();

        public static ИнформацияОТипе ПолучитьИнформациюОТипе(Type type)
        {
            ИнформацияОТипе ИТ = null;
            if (!ИнформацияПоТипу.TryGetValue(type,out ИТ))
            {
                ИТ = new ИнформацияОТипе(type);
                ИнформацияПоТипу[type] = ИТ;


            }
            return ИТ;
        }
       public ИнфoрмацияОМетоде(T MI)
        {
            Method = MI;

            ParameterInfo[] parameters = Method.GetParameters();
            hasParams = false;
            КоличествоПараметров = parameters.Length;
            if (КоличествоПараметров > 0)
            { 
                hasParams = parameters[parameters.Length - 1].GetCustomAttributes(typeof(ParamArrayAttribute), false).GetEnumerator().MoveNext();
            }

            if (hasParams)
            {
                TypeParams = parameters[parameters.Length - 1].ParameterType.GetElementType();
                ИнформацияОТипеЭлемента = ПолучитьИнформациюОТипе(TypeParams);

            }

            Параметры = new ИнформацияОТипе[КоличествоПараметров];

            for(int i=0;i< parameters.Length;i++)
            {

                Параметры[i] = ПолучитьИнформациюОТипе(parameters[i].ParameterType);

            }
        }

       public ИнфoрмацияОМетоде(ИнфoрмацияОМетоде<T> ИМ, int КолПарам)
        {
            Method = ИМ.Method;
            КоличествоПараметров = КолПарам;
            КоличествоПараметровПарамс = ИМ.КоличествоПараметров;
            hasParams = true;
            TypeParams = ИМ.TypeParams;
            ИнформацияОТипеЭлемента = ИМ.ИнформацияОТипеЭлемента;

            Параметры = new ИнформацияОТипе[КолПарам];

            for (int i = 0; i < КоличествоПараметровПарамс - 1; i++)
            {

                Параметры[i] =ИМ.Параметры[i];

            }

            
            var ИОТ= ПолучитьИнформациюОТипе(ИМ.TypeParams);

            for (int i = КоличествоПараметровПарамс - 1; i < КолПарам; i++)
            {

                Параметры[i] = ИОТ;

            }
        }

        // Добавить парамс как обычный метод
        public ИнфoрмацияОМетоде(ИнфoрмацияОМетоде<T> ИМ)
        {
            Method = ИМ.Method;
            КоличествоПараметров = ИМ.КоличествоПараметров;
            КоличествоПараметровПарамс = 0;
            hasParams = false;


            Параметры = ИМ.Параметры;
        }

        public bool Сравнить(Type[] параметры)
        {

            for (int i = 0; i < КоличествоПараметров ; i++)
            {

                if (!Параметры[i].Равняется(параметры[i]))
                      return false;

            }

            return true;
        }


       
        public bool СравнитьПарамс(Type[] параметры)
        {
           var ПоследнийПарам = КоличествоПараметров - 1;

            if (параметры.Length < ПоследнийПарам)
                return false;

            for (int i = 0; i < ПоследнийПарам; i++)
            {

                if (!Параметры[i].Равняется(параметры[i]))
                    return false;

            }

            
            
            
            for (int i = ПоследнийПарам; i < параметры.Length; i++)
            {

                if ( !ИнформацияОТипеЭлемента.Равняется(параметры[i]))
                    return false;

            }

            return true;
        }

        public object ВыполнитьМетод(object Target, params object[] input)
        {

            if (!hasParams)
                return Method.Invoke(Target, input);


            int последняяПозиция = КоличествоПараметров - 1;

                object[] realParams = new object[КоличествоПараметров];
                for (int i = 0; i < последняяПозиция; i++)
                    realParams[i] = input[i];

                
                Array массивПараметров = Array.CreateInstance(TypeParams, input.Length - последняяПозиция);
                for (int i = 0; i < массивПараметров.Length; i++)
                массивПараметров.SetValue(input[i + последняяПозиция], i);

                realParams[последняяПозиция] = массивПараметров;



            var res= Method.Invoke(Target, realParams);

            массивПараметров = (Array)realParams[последняяПозиция];
            for (int i = 0; i < массивПараметров.Length; i++)
                input[i + последняяПозиция] = realParams.GetValue(i);


            return res;


        }

    }
}



Тип для IsByRef узнаем через GetElementType();
var tint = typeof(int).MakeByRefType().GetElementType();



Для примера с CallA создаем массив по параметрам.
Для методов params разврачиваем params в массив параметров но нужного количества. В примере с
static public void CallA(params int[] args)


разворачиваем до
static public void CallA(int arg1,int arg1)



Если аргументы равны, то сравниваем сначала по params, а затем по количеству аргументов (сначала идут с большим аргументом)
То есть
static public void CallA(int arg1,params int[] args)
идет раньше, чем
static public void CallA(params int[] args)
и солнце б утром не вставало, когда бы не было меня
Отредактировано 15.06.2016 7:38 Serginio1 . Предыдущая версия . Еще …
Отредактировано 14.06.2016 13:53 Serginio1 . Предыдущая версия .
Отредактировано 10.06.2016 6:57 Serginio1 . Предыдущая версия .
Отредактировано 09.06.2016 12:02 Serginio1 . Предыдущая версия .
Отредактировано 09.06.2016 11:57 Serginio1 . Предыдущая версия .
Отредактировано 09.06.2016 11:01 Serginio1 . Предыдущая версия .
Отредактировано 09.06.2016 8:41 Serginio1 . Предыдущая версия .
Отредактировано 09.06.2016 8:35 Serginio1 . Предыдущая версия .
Re[13]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 10.06.16 04:35
Оценка:
Здравствуйте, Serginio1, Вы писали:
Хе. А ведь таиким макаром можно добавить для каждого типа типы содержащие методы расширители и их использовать при поиске нужно сигнатуры.
Кроме того можно использовать дженерик методы тип которых можно определить по типу параметров.

Тогда можно писать почти одинаково как на C#
и солнце б утром не вставало, когда бы не было меня
Re: .Net Core. Вызов манагед кода из натива
От: gnome  
Дата: 13.06.16 10:02
Оценка:
Здравствуйте, Serginio1, Вы писали:


Для начала попробуй http://bfy.tw/6Etw
Re[2]: .Net Core. Вызов манагед кода из натива
От: Sinix  
Дата: 13.06.16 12:10
Оценка:
Здравствуйте, gnome, Вы писали:

G>Для начала попробуй http://bfy.tw/6Etw


Добрый полезный совет: сначала ознакомиться с вопросом, затем набрасывать. Порядок важен А то как в этот раз выйдет — в результатах поиска 0 ответов по теме.

Топикстартер знает, как вызвать coreCLR из натива (в стартовом посте ссылки были). Проблема в другом: он хочет аналог COM interop на платформе, которая его пока не поддерживает.
Re[2]: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.06.16 13:58
Оценка:
Здравствуйте, gnome, Вы писали:

G>Здравствуйте, Serginio1, Вы писали:



G>Для начала попробуй http://bfy.tw/6Etw


Спасибо конечно, только нужно добавить Core Clr/
В этой ветке я уже дал решение
https://rsdn.ru/forum/dotnet/6463050.1
Автор: Serginio1
Дата: 06.06.16

https://rsdn.ru/forum/dotnet/6464225.1
Автор: Serginio1
Дата: 07.06.16
и солнце б утром не вставало, когда бы не было меня
Re[13]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 15.06.16 07:43
Оценка:
Здравствуйте, Serginio1, Вы писали:

Вобщем добавил код. Вроде работает

namespace CoreClrDLL
{

    public class СравнительМетодов<T> : IComparer<ИнфoрмацияОМетоде<T>>   where T : MethodBase
    {


        public int Compare(ИнфoрмацияОМетоде<T> A, ИнфoрмацияОМетоде<T> B)
        {
            int res = 0;
            for (int i=0; i< A.Параметры.Count(); i++)
            {

                res = A.Параметры[i].CompareTo(B.Параметры[i]);

                if (res != 0) return res;
            }

            res = A.hasParams.CompareTo(B.hasParams);

            if (res != 0) return res;


            res = -A.КоличествоПараметровПарамс.CompareTo(B.КоличествоПараметровПарамс);
            if (res != 0) return res;

            return A.Method.ToString().CompareTo(B.Method.ToString());
        }


       
    }

    public class СравнительМетодовСпарамс<T> : IComparer<ИнфoрмацияОМетоде<T>> where T : MethodBase
    {


        public int Compare(ИнфoрмацияОМетоде<T> A, ИнфoрмацияОМетоде<T> B)
        {


            int res = 0;
            res = -A.КоличествоПараметров.CompareTo(B.КоличествоПараметров);
            if (res != 0) return res;

            for (int i = 0; i < A.Параметры.Count() - 1; i++)
            {

                res = A.Параметры[i].CompareTo(B.Параметры[i]);

                if (res != 0) return res;
            }

            res = A.hasParams.CompareTo(B.hasParams);

            if (res != 0) return res;


           

            return A.Method.ToString().CompareTo(B.Method.ToString());
        }
    }
    public class ВсеМетодыПоИмени<T> where T : MethodBase
    {
         Dictionary<int, List<ИнфoрмацияОМетоде<T>>> ОбычныеМетоды=new Dictionary<int, List<ИнфoрмацияОМетоде<T>>>();

         List<ИнфoрмацияОМетоде<T>> МетодыСParams=new List<ИнфoрмацияОМетоде<T>>();

        void ДобавитьВСловарь(ИнфoрмацияОМетоде<T> им, int КоличествоПараметров)
        {
            List<ИнфoрмацияОМетоде <T>> СписокМетодов = null;

            if (!ОбычныеМетоды.TryGetValue(КоличествоПараметров, out СписокМетодов))
            {
                СписокМетодов = new List<ИнфoрмацияОМетоде<T>>();
                ОбычныеМетоды[КоличествоПараметров] = СписокМетодов;


            }


            СписокМетодов.Add(им);
        }

        void ДобавитПарамсВСписок(KeyValuePair<int, List<ИнфoрмацияОМетоде<T>>>[] Массив, ИнфoрмацияОМетоде<T> Им)
        {
            int минКолПарам = Им.КоличествоПараметров - 1;

            
            foreach (var кв in Массив)
            {

                if (кв.Key < минКолПарам) continue;


                var им = new ИнфoрмацияОМетоде<T>(Им, кв.Key);
                кв.Value.Add(им);

            }

        }
        void ДобавитьМетодыСпарамсВОбычныеМетоды()
        {

            var KV = ОбычныеМетоды.OrderBy(x => x.Key).ToArray();
            foreach (var им in МетодыСParams)
            {

                ДобавитПарамсВСписок(KV, им);


            }

            foreach (var kv in KV)
            {
                kv.Value.Sort(new СравнительМетодов<T>());

            }
        }
        public ВсеМетодыПоИмени(IEnumerable<T> методы)
        {

            foreach(var метод in методы)
            {

                var им = new ИнфoрмацияОМетоде<T>(метод);

                if (им.hasParams)
                {
                    МетодыСParams.Add(им);
                    var ОбычныйМетод = new ИнфoрмацияОМетоде<T>(им);
                    ДобавитьВСловарь(ОбычныйМетод, ОбычныйМетод.КоличествоПараметров);
                }
                else
                {

                    ДобавитьВСловарь(им, им.КоличествоПараметров);
                }

            }


            ДобавитьМетодыСпарамсВОбычныеМетоды();

            МетодыСParams.Sort(new СравнительМетодовСпарамс<T>());

         

        }

        public ИнфoрмацияОМетоде<T> НайтиМетод(object[] параметрыОбъекты)
        {

            Type[] параметры = new Type[параметрыОбъекты.Length];

            for (var i=0; i< параметрыОбъекты.Length; i++)
            {
                if (параметрыОбъекты[i] == null)
                    параметры[i] = null;
                else
                    параметры[i] = параметрыОбъекты[i].GetType();


            }
            List<ИнфoрмацияОМетоде<T>> СписокМетодов;

            if (ОбычныеМетоды.TryGetValue(параметры.Length, out СписокМетодов))
            {
                if (параметры.Length == 0) return СписокМетодов[0];

                foreach (var метод in СписокМетодов)
                {
                    if (метод.Сравнить(параметры))
                        return метод;

                }


            }


            foreach (var метод in МетодыСParams)
            {
                if (метод.СравнитьПарамс(параметры))
                    return метод;

            }

            return null;
        }
    }
}



И вызов



public static void НайтиИВыполнитьМетод(ВсеМетодыПоИмени<MethodInfo> ВсеМетоды, params object[] параметры)
        {
            var метод = ВсеМетоды.НайтиМетод(параметры);
            if (метод != null)
                   метод.ВыполнитьМетод(null, параметры);

        }
        public static void ТестПоискаМетода()
        {

            DynamicCall.SB.Clear();
            var методы = typeof(DynamicCall).GetMethods().Where(x => x.Name == "CallA").ToArray();

            var всеМетоды = new ВсеМетодыПоИмени<MethodInfo>(методы);
            //DynamicCall.CallADynamic(1, 2);
            //DynamicCall.CallADynamic(null, null);
            //DynamicCall.CallADynamic(null, new object());

            double d = 6;
            НайтиИВыполнитьМетод(всеМетоды, 2, d);
            НайтиИВыполнитьМетод(всеМетоды, 1, 2);
            НайтиИВыполнитьМетод(всеМетоды, null, null);
            НайтиИВыполнитьМетод(всеМетоды, null, new object());
            НайтиИВыполнитьМетод(всеМетоды, 1, new int[] { 1,2,3});

            string ss = DynamicCall.SB.ToString();
        }



Выдает

ref int+double
int+params
object+string
objects
int+params
и солнце б утром не вставало, когда бы не было меня
Re[7]: [Offtop] Вызов принят!
От: mDmitriy Россия  
Дата: 15.06.16 08:13
Оценка:
Здравствуйте, Serginio1, Вы писали:
S> С моим кодом пока работаю только я один. А я 1С ник. И мне удобнее работать с киррилицей.
S>К хорошему привыкаешь быстро. Попробуй
Какая гадость эта ваша заливая рыба(с)
Учитывая, что вся семантика шарпа на латинице (как это ни странно), любители непрерывно переключать раскладку несколько удивляют...
Не говоря уж о такой ерунде, как более лаконичный буржуйский язык
Re[8]: [Offtop] Вызов принят!
От: Sinix  
Дата: 15.06.16 08:24
Оценка: +2
Здравствуйте, mDmitriy, Вы писали:

D>Учитывая, что вся семантика шарпа на латинице (как это ни странно), любители непрерывно переключать раскладку несколько удивляют...


Ну так сказано же:

С моим кодом пока работаю только я один.

Если человека устраивает, что ни в одном проекте подобный код не примут и даже читать не будут — зачем спорить?
Re[9]: [Offtop] Вызов принят!
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 15.06.16 08:41
Оценка:
Здравствуйте, Sinix, Вы писали:


S>Если человека устраивает, что ни в одном проекте подобный код не примут и даже читать не будут — зачем спорить?


Главное работает и мне понятно. Вопрос где могут быть еще подводные камни.
Наверняка найдутся в режиме эксплуатации.

Поэкспериментировал с CallBack


[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
         delegate void myDelegate(IntPtr thisptr);

  public static void TestCallBack(IntPtr Str,IntPtr FuncPtr)
        {

            myDelegate fun = Marshal.GetDelegateForFunctionPointer<myDelegate>(FuncPtr);

            fun(Str);

            var str = Marshal.PtrToStringUni(Str);
        }



На С++

typedef void(STDMETHODCALLTYPE *ManagedTestCallBack)(const wchar_t*, void(*) (const wchar_t*));

    typedef void(STDMETHODCALLTYPE *ManagedTestCallBack)(const wchar_t*, void(*) (const wchar_t*));
    
void TestCallBack(const wchar_t* str)
{

    printf_s("Return string %S.\n", str);
}


    ManagedTestCallBack pTestCallBack;
    
    
    hr = CreateDelegate2(pCLRRuntimeHost, domainId, L"CoreClrDLL", L"CoreClrDLL.Program", L"TestCallBack", (INT_PTR*)&pTestCallBack);
        if (FAILED(hr))
        {
            printf_s("Failed to create a delegate to the managed entry point: (%d).\n", hr);
    
        }
        else
        {
            wchar_t* str = L"Test str from unmanaged";
            pTestCallBack(str, TestCallBack);
        }

ManagedTestCallBack pTestCallBack;


hr = CreateDelegate2(pCLRRuntimeHost, domainId, L"CoreClrDLL", L"CoreClrDLL.Program", L"TestCallBack", (INT_PTR*)&pTestCallBack);
    if (FAILED(hr))
    {
        printf_s("Failed to create a delegate to the managed entry point: (%d).\n", hr);

    }
    else
    {
        wchar_t* str = L"Test str from unmanaged";
        pTestCallBack(str, TestCallBack);
    }


Работает. Так что можно память выделять на стороне натива и использовать обратные вызовы.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 15.06.2016 9:25 Serginio1 . Предыдущая версия . Еще …
Отредактировано 15.06.2016 9:20 Serginio1 . Предыдущая версия .
Отредактировано 15.06.2016 9:19 Serginio1 . Предыдущая версия .
Re[8]: [Offtop] Вызов принят!
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 15.06.16 08:44
Оценка:
Здравствуйте, mDmitriy, Вы писали:

D>Здравствуйте, Serginio1, Вы писали:

S>> С моим кодом пока работаю только я один. А я 1С ник. И мне удобнее работать с киррилицей.
S>>К хорошему привыкаешь быстро. Попробуй
D>Какая гадость эта ваша заливая рыба(с)
D>Учитывая, что вся семантика шарпа на латинице (как это ни странно), любители непрерывно переключать раскладку несколько удивляют...
D>Не говоря уж о такой ерунде, как более лаконичный буржуйский язык

Просто ты не привык. В 1С наоборот плюются на латиницу.
А у меня «Руслиш»: официальный язык МКС
Не летать Вам в космос. А у меня есть шанс.
и солнце б утром не вставало, когда бы не было меня
Re[9]: [Offtop] Вызов принят!
От: mDmitriy Россия  
Дата: 16.06.16 08:58
Оценка:
Здравствуйте, Serginio1, Вы писали:
S> Просто ты не привык.
Нет... О вкусе устриц имеет смысл разговаривать с теми, кого от них не тошнит
S> В 1С наоборот плюются на латиницу.
А куда им деваться, бедолагам — выбора-то нет
S>А у меня «Руслиш»: официальный язык МКС
S> Не летать Вам в космос. А у меня есть шанс.
В пределах земной орбиты — есть
А космос — он несколько масштабнее
Re[10]: [Offtop] Вызов принят!
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.06.16 09:02
Оценка:
Здравствуйте, mDmitriy, Вы писали:

D>Здравствуйте, Serginio1, Вы писали:

S>> Просто ты не привык.
D>Нет... О вкусе устриц имеет смысл разговаривать с теми, кого от них не тошнит
S>> В 1С наоборот плюются на латиницу.
D>А куда им деваться, бедолагам — выбора-то нет
Есть множество локализаций. В том числе украинская и казахская

Например я на 1С тоже пишу.

Процедура ExtractFields(S,aList,Delimiter,QuoteChar)
    FieldStart=0; ScanField=1; ScanQuoted=2; EndQuoted=3;

   //{initialize by clearing the string list, and
   // starting in FieldStart state}
   // Assert(aList <> nil, 'TDExtractFields: list is nil');
    aList= новый Массив;
    if ( (S=неопределено) или (СтрДлина(S) =0 )) Тогда
        aList.Add("");
        return;
    КонецЕсли;

    State = FieldStart;

   //  RStringBuilder SB= new RStringBuilder();
    SB="";
    StartPos=1;
    EndPos=СтрДлина(S);
    Inx=1;

   // {read through all the characters in the string}
    while (Inx <=EndPos) Цикл

       //    {get the next character}
        Ch = Сред(S,Inx,1);

       //    {switch processing on the state}
        Если State =FieldStart Тогда

            if  ( Ch = QuoteChar) Тогда
                State = ScanQuoted;
                StartPos=Inx+1;
                SB="";
                Inx=НайтиВПодстроке(S,StartPos,QuoteChar);
                продолжить;
            else
                if ( Ch = Delimiter) Тогда


S>>А у меня «Руслиш»: официальный язык МКС

S>> Не летать Вам в космос. А у меня есть шанс.
D>В пределах земной орбиты — есть
D>А космос — он несколько масштабнее
и солнце б утром не вставало, когда бы не было меня
Re: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 16.06.16 11:17
Оценка:
Здравствуйте, Serginio1, Вы писали:



S>Начну с того, что в 1С есть технология Внешних компонент Native API Технология создания внешних компонент Технология создания внешних компонент которые работают как под Windows так и под Linux


Сделал маршалинг из натива в манагед

namespace CoreClrDLL
{

//    struct _tVariant
//    {
//        _ANONYMOUS_UNION union
//        {
//            int8_t i8Val;
//            int16_t shortVal;
//            int32_t lVal;
//        int intVal;
//        unsigned int uintVal;
//        int64_t llVal;
//        uint8_t ui8Val;
//        uint16_t ushortVal;
//        uint32_t ulVal;
//        uint64_t ullVal;
//        int32_t errCode;
//        long hRes;
//        float fltVal;
//        double dblVal;
//        bool bVal;
//        char chVal;
//        wchar_t wchVal;
//        DATE date;
//        IID IDVal;
//        struct _tVariant *pvarVal;
//        struct tm      tmVal;
//        _ANONYMOUS_STRUCT struct
//        {
//            void* pInterfaceVal;
//        IID InterfaceID;
//    }
//    __VARIANT_NAME_2/*iface*/;
//        _ANONYMOUS_STRUCT struct
//        {
//            char* pstrVal;
//    uint32_t strLen; //count of bytes
//}
//__VARIANT_NAME_3/*str*/;
//        _ANONYMOUS_STRUCT struct
//        {
//            WCHAR_T* pwstrVal;
//uint32_t wstrLen; //count of symbol
//        } __VARIANT_NAME_4/*wstr*/;
//    } __VARIANT_NAME_1;
//    uint32_t cbElements;    //Dimension for an one-dimensional array in pvarVal
//TYPEVAR vt;
//};
   public enum EnumVar
    {
        VTYPE_EMPTY = 0,
        VTYPE_NULL,
        VTYPE_I2,                   //int16_t
        VTYPE_I4,                   //int32_t
        VTYPE_R4,                   //float
        VTYPE_R8,                   //double
        VTYPE_DATE,                 //DATE (double)
        VTYPE_TM,                   //struct tm
        VTYPE_PSTR,                 //struct str    string
        VTYPE_INTERFACE,            //struct iface
        VTYPE_ERROR,                //int32_t errCode
        VTYPE_BOOL,                 //bool
        VTYPE_VARIANT,              //struct _tVariant *
        VTYPE_I1,                   //int8_t
        VTYPE_UI1,                  //uint8_t
        VTYPE_UI2,                  //uint16_t
        VTYPE_UI4,                  //uint32_t
        VTYPE_I8,                   //int64_t
        VTYPE_UI8,                  //uint64_t
        VTYPE_INT,                  //int   Depends on architecture
        VTYPE_UINT,                 //unsigned int  Depends on architecture
        VTYPE_HRESULT,              //long hRes
        VTYPE_PWSTR,                //struct wstr
        VTYPE_BLOB,                 //means in struct str binary data contain
        VTYPE_CLSID,                //UUID
        VTYPE_STR_BLOB = 0xfff,
        VTYPE_VECTOR = 0x1000,
        VTYPE_ARRAY = 0x2000,
        VTYPE_BYREF = 0x4000,    //Only with struct _tVariant *
        VTYPE_RESERVED = 0x8000,
        VTYPE_ILLEGAL = 0xffff,
        VTYPE_ILLEGALMASKED = 0xfff,
        VTYPE_TYPEMASK = 0xfff
    };

    public class РаботаСВариантами
    {
      public static  object ПолучитьОбъекИзIntPtr(IntPtr Элемент)
        {
            IntPtr текПоз = Элемент + 44;
            int размерIntPtr = Marshal.SizeOf<IntPtr>();
            EnumVar тип =(EnumVar) Marshal.ReadInt16(текПоз);

            switch (тип)
            {
                case EnumVar.VTYPE_EMPTY:
                case EnumVar.VTYPE_NULL: return null;
                case EnumVar.VTYPE_I2: return Marshal.ReadInt16(Элемент);
                case EnumVar.VTYPE_I4: return Marshal.ReadInt32(Элемент);
                case EnumVar.VTYPE_R4: return Marshal.PtrToStructure<float>(Элемент);
                case EnumVar.VTYPE_R8: return Marshal.PtrToStructure<double>(Элемент);
                case EnumVar.VTYPE_BOOL:return Marshal.ReadByte(Элемент)!=0;
                case EnumVar.VTYPE_I1: return (sbyte)Marshal.ReadByte(Элемент);
                case EnumVar.VTYPE_UI1: return Marshal.ReadByte(Элемент);
                case EnumVar.VTYPE_UI2: return (UInt16)Marshal.ReadInt16(Элемент);

                case EnumVar.VTYPE_UI4: return (UInt32)Marshal.ReadInt32(Элемент);

                case EnumVar.VTYPE_I8: return Marshal.ReadInt64(Элемент);
                case EnumVar.VTYPE_UI8: return (UInt64)Marshal.ReadInt64(Элемент);
                case EnumVar.VTYPE_PWSTR: return Marshal.PtrToStringUni(Marshal.ReadIntPtr(Элемент));

                case EnumVar.VTYPE_BLOB:
                    текПоз = Элемент + размерIntPtr;
                    byte[] res = new byte[Marshal.ReadInt32(текПоз)];
                    Marshal.Copy(Marshal.ReadIntPtr(Элемент), res,0,res.Length);
                    return res;
            }
            return null;
            }



        }
}



static object[] ПолучитьМассивПараметров(IntPtr МассивПараметров, int РазмерМассива)
        {

            var result = new object[РазмерМассива];
            IntPtr ТекПоз = МассивПараметров;
            for (var i=0; i< result.Length; i++)
            {
                result[i] = РаботаСВариантами.ПолучитьОбъекИзIntPtr(ТекПоз);

                ТекПоз += 48;
            }

            return result;
        }
        public static bool CallAsFunc(int Target, IntPtr ИмяМетодаPtr, IntPtr ReturnValue, IntPtr МассивПараметров,int РазмерМассива)
            {

            string ИмяМетода = Marshal.PtrToStringUni(ИмяМетодаPtr);
            var параметры = ПолучитьМассивПараметров(МассивПараметров, РазмерМассива);
            return true;

        }




На С++

typedef void(STDMETHODCALLTYPE *ManagedCallAsFunc)(const __int32, const wchar_t*, tVariant* pvarRetValue, tVariant* paParams, const __int32  lSizeArray);

ManagedCallAsFunc  pCallAsFunc;

hr = CreateDelegate2(pCLRRuntimeHost, domainId, L"CoreClrDLL", L"CoreClrDLL.Program", L"CallAsFunc", (INT_PTR*)&pCallAsFunc);
    if (FAILED(hr))
    {
        printf_s("Failed to create a delegate to the managed entry point: (%d).\n", hr);

    }
    else
    {
        //(const __int32, const wchar_t*, tVariant* pvarRetValue, tVariant* paParams, const __int32  lSizeArray);
        wchar_t* str = L"Test str from unmanaged";
        tVariant* paParams = new tVariant[4];
        tVariant* paP = paParams;
        paP->vt = VTYPE_I4;
        paP->lVal = 8;

        paP++;

        paP->vt = VTYPE_BOOL;
        paP->lVal = true;

        paP++;
        paP->vt = VTYPE_PWSTR;
        paP->pwstrVal = str;

        byte* pb = new byte[4]; pb[0] = 27; pb[1] = 28; pb[2] = 29; pb[3] = 30;
        paP++;
        paP->vt = VTYPE_BLOB;
        paP->pstrVal = (char*)pb;
        paP->strLen = 4;
        pCallAsFunc(-1, str, 0, paParams, 4);
    }


Вроде нормально отрабатывает
и солнце б утром не вставало, когда бы не было меня
Re[13]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.06.16 07:22
Оценка:
Здравствуйте, Serginio1, Вы писали:

Добавил простенький список для хранения объектов

 public struct ЭлементХранилища
    {
        internal AutoWrap Объект;
        internal int Next;


       internal ЭлементХранилища(AutoWrap Объект)
        {

            this.Объект = Объект;
            Next = -1;
        }

        internal ЭлементХранилища(AutoWrap Объект, int next)
        {

            this.Объект = Объект;
            Next = next;
        }
    }

   internal class ХранилищеОбъектов
    {
     
         List<ЭлементХранилища> Элементы= new List<ЭлементХранилища>();
         int FirstDeleted = -1;

        public int Add(AutoWrap Объект)
        {



            var элемент = new ЭлементХранилища(Объект);




            if (FirstDeleted == -1)
            { Элементы.Add(элемент);
                return Элементы.Count-1;
            }
            else
            {
               int newPos = FirstDeleted;
                FirstDeleted = Элементы[newPos].Next;
                Элементы[newPos] = элемент;
                return newPos;

            }
 
        }

        public void RemoveKey(int Pos)
        {
            if (Pos > -1 && Pos < Элементы.Count && Элементы[Pos].Объект != null)
            {
               
                var Элемент = new ЭлементХранилища(null, FirstDeleted);
                Элементы[Pos] =Элемент;
            
                FirstDeleted = Pos;
            }
                           


        }

        public AutoWrap GetValue(int Pos)
        {

            if (!(Pos > -1 && Pos < Элементы.Count && Элементы[Pos].Объект != null))
                return null;

            return Элементы[Pos].Объект;

        }

    }



Создал класс обертку

public class AutoWrap
    {
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        internal delegate IntPtr ВыделитьПамятьDelegate(int КоличествоБайтов);

        internal static ХранилищеОбъектов СписокОбъектов;
        internal static int ХэшДляСсылки=new Guid().GetHashCode();


        protected internal object O = null;
        protected internal Type T = null; // Тип может быть и интерфейсом
        protected internal int ИндекасВСписке;


        internal bool ЭтоТип;
        internal bool IsEnum;
        internal bool ЭтоExpandoObject;
        internal static bool ЭтоСемерка = false;
        internal static bool ВыводитьСообщениеОбОшибке = true;
        internal static Exception ПоследняяОшибка = null;

        internal static ВыделитьПамятьDelegate ВыделитьПямять;

        public static void SetDelegate(IntPtr ДляВыделенияПамяти)
        {
            ВыделитьПямять = Marshal.GetDelegateForFunctionPointer<ВыделитьПамятьDelegate>(ДляВыделенияПамяти);

        }
        static AutoWrap()
        {
            СписокОбъектов = new ХранилищеОбъектов();
            var первый = new AutoWrap(typeof(NetObjectToNative));

        }


        public AutoWrap(object obj)
        {

            ИндекасВСписке = СписокОбъектов.Add(this);
            O = obj;
            if (O is Type)
            {
                T = O as Type;
                ЭтоТип = true;
            }
            else
            {
                T = O.GetType();
                ЭтоТип = false;
                ЭтоExpandoObject = O is System.Dynamic.ExpandoObject;
                IsEnum = T.GetTypeInfo().IsEnum;


            }



Экспортируются функции
 public static bool CallAsFunc(int Target, IntPtr ИмяМетодаPtr, IntPtr ReturnValue, IntPtr МассивПараметров, int РазмерМассива)
        {
            var AW = СписокОбъектов.GetValue(Target);

            if (AW == null) return false;

            bool IsReturnValue = ReturnValue != IntPtr.Zero;

            string ИмяМетода = Marshal.PtrToStringUni(ИмяМетодаPtr);
            var параметры = ПолучитьМассивПараметров(МассивПараметров, РазмерМассива);

            object result = null;
            List<int> ИзмененныеПараметры = new List<int>();

           

            var res = AW.TryInvokeMember(ИмяМетода, параметры, out result, ИзмененныеПараметры);
            if (!res) return false;

            foreach( var i in ИзмененныеПараметры)
            {
                РаботаСВариантами.УстановитьОбъектВIntPtr(параметры[i], МассивПараметров+48*i);

            }

            if (IsReturnValue) РаботаСВариантами.УстановитьОбъектВIntPtr(ОбернутьОбъект(result), ReturnValue);

            return true;

        }

      public static   int GetNParams(int Target, IntPtr ИмяМетодаPtr)
{
            var AW = СписокОбъектов.GetValue(Target);
            if (AW == null) return -1;

            string ИмяМетода = Marshal.PtrToStringUni(ИмяМетодаPtr);
            return ИнформацияПоТипам.КоличествоПараметровДляМетода(AW.T, ИмяМетода);

        }

    public static  bool SetPropVal(int Target, IntPtr ИмяСвойстваPtr, IntPtr pvarPropVal)
{

            var AW = СписокОбъектов.GetValue(Target);
            if (AW == null) return false;

            string ИмяСвойства = Marshal.PtrToStringUni(ИмяСвойстваPtr);

            object result = РаботаСВариантами.ПолучитьОбъекИзIntPtr(pvarPropVal);

            var res = AW.TrySetMember(ИмяСвойства,result);
            

            return res;
}
        //---------------------------------------------------------------------------//
        public static bool GetPropVal(int Target, IntPtr ИмяСвойстваPtr, IntPtr varPropVal)
{
            var AW = СписокОбъектов.GetValue(Target);
            if (AW == null) return false;

            string ИмяСвойства = Marshal.PtrToStringUni(ИмяСвойстваPtr);

            object result = null;
            var res = AW.TryGetMember(ИмяСвойства, out result);
            if (!res) return false;

            РаботаСВариантами.УстановитьОбъектВIntPtr(ОбернутьОбъект(result), varPropVal);

            return true;
}

        public static void DeleteObject(int Target)
        {
            СписокОбъектов.RemoveKey(Target);

        }




Код на C#
var sB= new System.Text.StringBuilder();
sB.Append("Новая Строка");
var str=sB.ToString();
sB.Capacity=40;
var capacity=sB.Capacity


На С++ выглядит так

// Загрузим Core CLR
    // И создадим домен
    //Первый параметр это путь к папке с coreclr.dll
    NetObjectToNative::ManagedDomainLoader* mD = NetObjectToNative::ManagedDomainLoader::InitManagedDomain(L"c:\\Program Files\\DNX\\runtimes\\dnx-coreclr-win-x86.1.0.0-rc1-update1\\bin\\", L"", L"");

    if (!mD)  return 0;

    tVariant Params[4];
    tVariant RetVal;
    tVariant* paParams = Params;

    paParams->vt = VTYPE_PWSTR;
    paParams->pwstrVal = L"System.Text.StringBuilder";

    cout << "Press Key";
    cin.get();

    // 0 это индекс вспомогательного класса для получения типов объектов и прочих удобный методов
   bool res=mD->pCallAsFunc(0, L"Новый", &RetVal, paParams, 1);
   if(!res) return 0;


   // Так как в 1С нет возможности установить пользовательский тип
   // то возвращаем byte[12] который будет ID объекта
   // первые четыре байта ХэшДляСсылки=new Guid().GetHashCode(); одинаковый для всех .Net объектов
   // вторые 4 байта это хэш объекта
   // третьи это индекс в списке экспортируемых объектов
   // Можно его передавать в качестве параметра типа BLOB
   byte ref[12];
   memcpy(ref, RetVal.pstrVal, 12);
   // Теперь мы можем передавать ссылку ref в параметрах;
   long* target =(long*)RetVal.pstrVal;

   long Target = target[2]; // Получили индекс в списке
   
   wprintf_s(L"index : %d\n", Target);

   // Память выделяется на стороне натива. Нам и удалять.
   delete[] RetVal.pstrVal;

   paParams->vt = VTYPE_PWSTR;
   paParams->pwstrVal = L"Новая Строка";

// 0 так как вызывается как void даже если метод что то и возвращает, что бы не оборачивать результат
    res = mD->pCallAsFunc(Target, L"Append", 0, paParams, 1);

    res = mD->pCallAsFunc(Target, L"ToString", &RetVal, paParams, 0);
    wprintf_s(L"index : %S\n", RetVal.pwstrVal);

    delete[] RetVal.pstrVal;

    paParams->vt = VTYPE_I4;
    paParams->lVal =40;
    res = mD->pSetPropVal(Target, L"Capacity", paParams);


    res = mD->pGetPropVal(Target, L"Capacity", &RetVal);
    wprintf_s(L"Capacity : %d\n", RetVal.lVal);

    // Удалим объект из списка. Теперь его может собрать GC
    mD->pDeleteObject(Target);
    
    // Создадим объект через тип

    paParams->vt = VTYPE_PWSTR;
    paParams->pwstrVal = L"System.Text.StringBuilder";
// Получим ID оббъекта typeof(System.Text.StringBuilder)
    res = mD->pCallAsFunc(0, L"ПолучитьТип", &RetVal, paParams, 1);

    //paParams[0] = RetVal;

    // Скопируем ID оббъекта typeof(System.Text.StringBuilder)
    memcpy(ref, RetVal.pstrVal, 12);

    // Установим ссылку в параметрах
    paParams->vt = VTYPE_BLOB;
    paParams->pstrVal =(char*) ref;
    paParams->strLen = 12;


    // И создадим экземпляр StringBuilder
    res = mD->pCallAsFunc(0, L"Новый", &RetVal, paParams, 1);
    if (!res) return 0;


    // Выгрузим домен
    delete mD;

    return 0;


Думаю статью написать. Как для C++ лучше сделать обертку. Для 1С думаю доделать на этой неделе
и солнце б утром не вставало, когда бы не было меня
Отредактировано 23.06.2016 6:38 Serginio1 . Предыдущая версия . Еще …
Отредактировано 22.06.2016 7:30 Serginio1 . Предыдущая версия .
Отредактировано 22.06.2016 7:25 Serginio1 . Предыдущая версия .
Re: .Net Core. Вызов манагед кода из натива
От: pilgrim_ Россия  
Дата: 22.06.16 09:25
Оценка: +1
Здравствуйте, Serginio1, Вы писали:

S>Но хотелось бы прикрутить этот аналог к Linux используя ВК Native API На просторах интернета нашел ссылки вызова управляемого кода из неуправляемого http://forums.dotnetfoundation.org/t/how-to-call-a-net-core-library-from-native-code-on-linux/1576/2


S>This C++ app allows to run custom C# method from compiled C# .dll on Linux and OS X using coreCLR


Я правильно понимаю, что основная проблема в том, что COre CLR не поддерживает COM Interop на не-windows платформах(вот тут
Автор: Sinix
Дата: 13.06.16
Sinix дал ссылку) ?

Но делегаты и структуры он умеет маршалить на не-windows платформах?

Если да, то можно описать на стороне C/C++ интерфейс (на C — структура с указателями на функции, на C++ сразу интерфейс — класс с чистыми вируальными методами), на стороне .NET описать native-"интерфейс" стуктуру/класс, с полями-делегатами соотв. методам в интерфейсе в C/C++.
Ключевое тут — чтобы Core CLR умел маршалить делегаты в структуре, "большой" .NEt это умеет, со 2-й версии точно.
Re[2]: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.06.16 09:50
Оценка:
Здравствуйте, pilgrim_, Вы писали:


_>Ключевое тут — чтобы Core CLR умел маршалить делегаты в структуре, "большой" .NEt это умеет, со 2-й версии точно.



Я так и делаю. Смотри
http://rsdn.ru/forum/dotnet/6478527.1
Автор: Serginio1
Дата: 22.06.16

http://ru.stackoverflow.com/questions/523386/%d0%92%d1%8b%d0%b7%d0%be%d0%b2-%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d1%8f%d0%b5%d0%bc%d0%be%d0%b3%d0%be-%d0%ba%d0%be%d0%b4%d0%b0-net-core-%d0%b8%d0%b7-%d0%bd%d0%b5%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d1%8f%d0%b5%d0%bc%d0%be%d0%b3%d0%be
и солнце б утром не вставало, когда бы не было меня
Отредактировано 22.06.2016 9:50 Serginio1 . Предыдущая версия .
Re: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 24.06.16 07:52
Оценка: 66 (1)
Здравствуйте, Serginio1, Вы писали:


Ну не прошло и 2 недели. Сделал и для 1С.

Перем   Врап,СсылкаНаДомен;
Функция СоздатьОбъектПоСсылке(Ссылка)
    
    рез = Новый("AddIn.NetObjectToNative.NetObjectToNative");
    рез.УстановитьСсылку(СсылкаНаДомен,Ссылка);    
    возврат  рез
КонецФункции // СоздатьОбъектПоСсылке()


Процедура КнопкаВыполнитьНажатие(Кнопка)
    
    СылкаСБ=Врап.Новый("System.Text.StringBuilder","Первая Строка");
    СсылкаCultureInfo=Врап.ПолучитьТип("System.Globalization.CultureInfo");
    
    СсылкаCultureInfoES=Врап.Новый(СсылкаCultureInfo,"es-ES");
    
    // 
    СultureInfo=СоздатьОбъектПоСсылке(СсылкаCultureInfo);
    
    СБ=СоздатьОбъектПоСсылке(СылкаСБ);
    Сообщить(СБ.Capacity);
    Сообщить(СБ.ПолучитьСсылку());
    
    СсылкаInvariantCulture=СultureInfo.InvariantCulture;
    
    // К сожалению 1С вызывает метод имеющий возвращаемое значение как функцию даже если вызов идет как процедура
    //Нужно очистить ссылку в списке объектов
    ссылка=Сб.Append("Новая Строка"); Врап.ОчиститьСсылку(ссылка);
    ссылка=Сб.AppendLine();   Врап.ОчиститьСсылку(ссылка);
    ссылка=Сб.Append("Вторая Строка"); Врап.ОчиститьСсылку(ссылка);
    ссылка=Сб.AppendLine();     Врап.ОчиститьСсылку(ссылка);
    
    ссылка=Сб.AppendFormat("AppendFormat {0}, {1}, {2}, {3}, {4},", "Строка", 21, 45.89, ТекущаяДата(),истина );   Врап.ОчиститьСсылку(ссылка);
    ссылка=Сб.AppendLine(); Врап.ОчиститьСсылку(ссылка);
    
    // Так как в параметрах можно передавать только простые типы закодирум ссылку на объект в строку
    ссылка=Сб.AppendFormat(СсылкаCultureInfoES,"AppendFormat {0}, {1}, {2}, {3}, {4},", "Строка", 21, 45.89, ТекущаяДата(),истина );  Врап.ОчиститьСсылку(ссылка);
    ссылка=Сб.AppendLine(); Врап.ОчиститьСсылку(ссылка);
    
    ссылка=Сб.AppendFormat(СсылкаInvariantCulture,"AppendFormat {0}, {1}, {2}, {3}, {4},", "Строка", 21, 45.89, ТекущаяДата(),истина ); 
    Врап.ОчиститьСсылку(СсылкаInvariantCulture);
    
    
    
    
    
    Сообщить(СБ.ToString());
    СБ.Capacity=40;
    Сообщить(СБ.Capacity);
    
    // Очистка ссылок СБ и  СultureInfo осуществляется внутри ВК
КонецПроцедуры

Процедура ПриОткрытии() 
    
    
    ИмяФайла="d:\MyPrograms\VNCOMP83\AddInNetObjectToNative\AddInNetObjectToNative\Debug\AddInNetObjectToNative.dll";
    
    ПодключитьВнешнююКомпоненту(ИмяФайла, "NetObjectToNative",ТипВнешнейКомпоненты.Native); 
    Врап = Новый("AddIn.NetObjectToNative.LoaderCLR");
    CoreClrDir="c:\Program Files\DNX\runtimes\dnx-coreclr-win-x86.1.0.0-rc1-update1\bin\";
    ДиректорияNetObjectToNative="d:\MyPrograms\VNCOMP83\NetObjectToNative\NetObjectToNative\bin\Debug\";
    
    СсылкаНаДомен=Врап.СоздатьОбертку(CoreClrDir,ДиректорияNetObjectToNative,"");
    
КонецПроцедуры


Пока сделал для Win. Допилю еще вызовы методов расширений. Вызов дженериков определяемых по типу.

Но помоему никому это не надо.
и солнце б утром не вставало, когда бы не было меня
Отредактировано 24.06.2016 8:04 Serginio1 . Предыдущая версия .
Re[2]: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 24.06.16 09:43
Оценка:
Здравствуйте, Serginio1, Вы писали:
Кстати в первоначальном примере ошибка прокралась

СылкаСБ=Врап.Новый("System.Text.StringBuilder","Первая Строка"); 
//Сообщить(СылкаСБ); 

СсылкаCultureInfo=Врап.ПолучитьТип("System.Globalization.CultureInfo"); 

    СсылкаCultureInfo=Врап.Новый(СсылкаCultureInfo,"es-ES"); 
// Здесь уже СсылкаCultureInfo указывает на объект 

// 
    СultureInfo=СоздатьОбъектПоСсылке(СсылкаCultureInfo); 

И СultureInfo это не тип а объект СсылкаCultureInfo,"es-ES");   

   
// Вызываем статический метод     
    СсылкаInvariantCulture=СultureInfo.InvariantCulture;

он проходит, так как нет проверки на статик.

Я думаю так и оставить. Можно из объекта как в Delphi вызывать и методы объекта и статические
и солнце б утром не вставало, когда бы не было меня
Re: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 24.06.16 11:18
Оценка:
Здравствуйте, Serginio1, Вы писали:



Столкнулся с такой проблемй.
Если Загрузить в 1с CLR
hr = pfnGetCLRRuntimeHost(IID_ICLRRuntimeHost2, (IUnknown**)&pCLRRuntimeHost);
А затем выгрузить и повторно попробовать загрузить. То получаем недопустимую операцию.


Вторая проблема это то, что можно создать только один домен и его нельзя выгружать.
и солнце б утром не вставало, когда бы не было меня
Re: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 28.06.16 08:58
Оценка:
Здравствуйте, Serginio1, Вы писали:

Сделал тестовый класс

namespace TestDllForCoreClr
{
    public class Тестовый
    {
        public static string Поле = "Статическое поле";
        public string СвойствоОбъекта { get; set; }

        public  Тестовый(string СвойствоОбъекта)
            {
            this.СвойствоОбъекта = СвойствоОбъекта;
            }

        public string ПолучитьСтроку()
        {

            return "Привет из CoreClr";
        }

        public int ПолучитьЧисло(int число)
        {

            return число;
        }
    }
}



И вызов из С++

//Теперь Создадим эклемпляр класса из сторонней сборки
    paParams->vt = VTYPE_PWSTR;
    paParams->pwstrVal = L"TestDllForCoreClr.Тестовый, TestDllForCoreClr, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";

    auto par2 = paParams;
    par2++;
    par2->vt = VTYPE_PWSTR;
    par2->pwstrVal = L"Свойство из Конструктора";
    res = mD->pCallAsFunc(0, L"Новый", &RetVal, paParams, 2);

    long testRef = GetTarget(&RetVal);
    paParams->vt = VTYPE_I4;
    paParams->lVal = 3;

    res = mD->pCallAsFunc(testRef, L"ПолучитьЧисло", &RetVal, paParams, 1);
    wprintf_s(L"input int : %d\n", RetVal.lVal);


    TestCallMethod(mD, testRef);
    TestCallMethod(mD, testRef);
    TestCallMethod(mD, testRef);




Ну и вызов миллиона нетовской функции

void TestCallMethod(NetObjectToNative::ManagedDomainLoader* mD, long Target)
{
    tVariant Params[4];
    tVariant RetVal;
    tVariant* paParams = Params;
    typedef std::chrono::high_resolution_clock Clock;
    auto start = Clock::now();
    

    long r = 0;
    for (int i = 0; i < 1000000; i++)
    {
        
        paParams->lVal = i;
        paParams->vt = VTYPE_I4;
        mD->pCallAsFunc(Target, L"ПолучитьЧисло", &RetVal, paParams, 1);
        
        r += RetVal.lVal;
        r %= 1 << 30;

    }

    auto finish = Clock::now();


    auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(finish - start).count() / 1000000000.0;


    wprintf_s(L"Tme=:  %.2f  second\n", elapsed);
    wprintf_s(L"Eval Value=:  %d \n", r);
}


Получилось около 3 сек 2.8, на моем i3-2120 3.3 GHz

Может я что делаю не так?


// Сначала хотел закодировать ссылку в byte[]
// Но 1С может передавать в параметрах только булево,дату, числа и строки

long GetTarget(tVariant* CurParam)
{
    wchar_t* curstr = CurParam->pwstrVal;
    curstr += 13;
    wstring temp = curstr;
    return stol(temp);

}
и солнце б утром не вставало, когда бы не было меня
Отредактировано 28.06.2016 9:09 Serginio1 . Предыдущая версия .
Re: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 01.07.16 08:11
Оценка: 2 (1)
Здравствуйте, Serginio1, Вы писали:

Выложил статью Кроссплатформенное использование классов .Net из неуправляемого кода. Или аналог IDispatch на Linux
Исходники лежат Здесь
и солнце б утром не вставало, когда бы не было меня
Re: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 01.07.16 10:29
Оценка:
Здравствуйте, Serginio1, Вы писали:

Выложил статью
Разработка → Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux
Исходники здесь
и солнце б утром не вставало, когда бы не было меня
Re[10]: Приоритет вызова перегруженных методов
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 06.07.16 11:45
Оценка: 69 (2)
Здравствуйте, Sinix, Вы писали:

Для Динамиков нашел решение
https://gist.github.com/jflam/777574
https://github.com/mgravell/fast-member/blob/master/FastMember/CallSiteCache.cs

На основании сделал для разного рода DynamicObject


using System.Text;
using System.Threading.Tasks;
using System.Linq.Expressions;
using Microsoft.CSharp.RuntimeBinder;
using System.Dynamic;
using System.Runtime.CompilerServices;
namespace Тестовый
{
   public class DynamicInvoker
    {
       public static object InvokeMember(object target, string methodName, params object[] args)
        {
            var targetParam = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null);
            CSharpArgumentInfo[] parameterFlags = new CSharpArgumentInfo[args.Length + 1];
            System.Linq.Expressions.Expression[] parameters = new System.Linq.Expressions.Expression[args.Length + 1];
            parameterFlags[0] = targetParam;
            parameters[0] = System.Linq.Expressions.Expression.Constant(target);
            for (int i = 0; i < args.Length; i++)
            {
                parameterFlags[i + 1] = CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant | CSharpArgumentInfoFlags.UseCompileTimeType, null);
                parameters[i + 1] = System.Linq.Expressions.Expression.Constant(args[i]);
            }
            var csb = Binder.InvokeMember(CSharpBinderFlags.None, methodName, null, typeof(DynamicInvoker), parameterFlags);
            var de = DynamicExpression.Dynamic(csb, typeof(object), parameters);
            LambdaExpression expr = System.Linq.Expressions.Expression.Lambda(de);
            return expr.Compile().DynamicInvoke();
        }

        public static object GetValue(object target,string name)
        {
            
            CallSite<Func<CallSite, object, object>> callSite = CallSite<Func<CallSite, object, object>>.Create(Binder.GetMember(CSharpBinderFlags.None, name, typeof(DynamicInvoker), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
               
            return callSite.Target(callSite, target);
        }
        public static void SetValue(object target, string name,  object value)
        {
          
                CallSite<Func<CallSite, object, object, object>> callSite = CallSite<Func<CallSite, object, object, object>>.Create(Binder.SetMember(CSharpBinderFlags.None, name, typeof(DynamicInvoker), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null) }));
                callSite.Target(callSite, target, value);
        }


    }
}



И вызов


void ВывестиСвойство(object target, string ИмяСвойства)
        {
            textBox.AppendText(ИмяСвойства+"="+DynamicInvoker.GetValue(target, ИмяСвойства).ToString() + Environment.NewLine);

        }
        private void button_Click(object sender, RoutedEventArgs e)
        {
            dynamic res = new ExpandoObject();
            res.Имя = "Тест ExpandoObject";
            res.Число = 456;
            res.ВСтроку = (Func<string>)(() => res.Имя);
            res.Сумма = (Func<int,int,int>)((x,y) => x+y);

            textBox.Clear();
            textBox.AppendText("ВСтроку="+DynamicInvoker.InvokeMember(res, "ВСтроку").ToString()+Environment.NewLine);
            textBox.AppendText("Сумма=" + DynamicInvoker.InvokeMember(res, "Сумма", 1, 2).ToString() + Environment.NewLine);

            ВывестиСвойство(res, "Имя");
            ВывестиСвойство(res, "Число");

            DynamicInvoker.SetValue(res, "Имя","Новое Имя");
            DynamicInvoker.SetValue(res, "Число","768");

            ВывестиСвойство(res, "Имя");
            ВывестиСвойство(res, "Число");

        }
и солнце б утром не вставало, когда бы не было меня
Отредактировано 06.07.2016 13:55 Serginio1 . Предыдущая версия .
Re: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 13.07.16 12:43
Оценка:
Здравствуйте, Serginio1, Вы писали:

Добави вывод типов для дженерик методов
Теперь можно не выводить отдельно метод


// public T ДженерикМетод<V, T>(V param1, T param2, V param3) 
Сообщить(Тест.ДженерикМетод(1,"Привет",3));
//


//public V ДженерикМетод2<K, V>(Dictionary<K, V> param1, K param2, V param3)

Словарь= ъНовый("System.Collections.Generic.Dictionary`2[System.Int32,System.String]");
Сообщить(Тест.ДженерикМетод2(Словарь.ПолучитьСсылку(),3,"Привет2"));

// public K ДженерикМетод3<K>(IList<K> param1, int param2, K param3)

List=ъНовый("System.Collections.Generic.List`1[System.String]");
Сообщить(Тест.ДженерикМетод3(List.ПолучитьСсылку(),3,"Привет3"));
и солнце б утром не вставало, когда бы не было меня
Re: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 19.07.16 12:21
Оценка:
Здравствуйте, Serginio1, Вы писали:

Сделал поддержку внешнего события
В классе создадим поле типа Action<string, string, string>


public class Тестовый 
    { 
      public Action<string, string, string>   ВнешнееСобытие1С;

// И сделаем эмуляцию события.



public async void TestВнешнегоСобытия() 
        { 
            for(int i=0;i<100; i++)
            {
                var значение = i.ToString();
                Task.Run(async() =>
                {
                   await Task.Delay(1000).ConfigureAwait(false);
                   this?.ВнешнееСобытие1С("Тестовый", "ТестовоеСообщение", значение);
                });

                await Task.Delay(50).ConfigureAwait(false);
            }


        }


В 1С.

Процедура ВнешнееСобытие(Источник, Событие, Данные)
    // Вставить содержимое обработчика.

    
    Сообщить("Источник="+Источник);
    Сообщить("Событие="+Событие);
    Сообщить("Данные="+Данные);
КонецПроцедуры

Процедура ТестВнешнегоСобытияНажатие(Элемент)
    // Вставить содержимое обработчика.

    Тестовый=ъТип("TestDllForCoreClr.Тестовый, TestDllForCoreClr, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");

Тест=ъ(Врап.Новый(Тестовый.ПолучитьСсылку()," Свойство из Конструктора")); 

Делегат=Ъ(Врап.ПолучитьДелегатВнешнегоСобытия1C());
Тест.ВнешнееСобытие1С=Делегат.ПолучитьСсылку();
Тест.TestВнешнегоСобытия();
КонецПроцедуры


И не забыть в Переменных модуля установить
Перем   Тест;
и солнце б утром не вставало, когда бы не было меня
Re: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 27.07.16 13:01
Оценка:
Здравствуйте, Serginio1, Вы писали:

Добавил поддержку параметров по умолчанию

Добавил поддержку параметров по умолчанию
// Тест вызова метода с параметрами по умолчанию

//public static int OptionalParam(int x, int y, int z = 5, int s = 4,string str="Привет")
    //       {
    //           return x + y + z + s;
    //       }





Сообщить("OptionalParam(int x, int y)="+Тестовый.OptionalParam(1,2));
    Сообщить("OptionalParam(int x, int y, int z = 5)="+Тестовый.OptionalParam(1,2,3));
    Сообщить("OptionalParam(int x, int y, int z = 5, int s,string str)="+Тестовый.OptionalParam(1,2,3,4,"ХаХа"));


Теперь думаю прикрутить методы расширению.
Можно к каждому типу прикрутить типы реализующих расширения.
Поиск провести по типу и сборкам. Может есть какие то другие решения?
и солнце б утром не вставало, когда бы не было меня
Re: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.08.16 08:39
Оценка:
Здравствуйте, Serginio1, Вы писали:

Прошу совета по блокировкам. Есть такая конструкция для хранения объектов одного типа.

 public struct ЭлементХранилища
    {
        internal AutoWrap Объект;
        internal int Next;


        internal ЭлементХранилища(AutoWrap Объект)
        {

            this.Объект = Объект;
            Next = -1;
        }

        internal ЭлементХранилища(AutoWrap Объект, int next)
        {

            this.Объект = Объект;
            Next = next;
        }
    }

    internal class ХранилищеОбъектов
    {
        const int НачальноеКоличествоЭлементов = 2;
        ЭлементХранилища[] Элементы = new ЭлементХранилища[НачальноеКоличествоЭлементов];
        int КоличествоЭлементов = 0;
        int РазмерМассива = НачальноеКоличествоЭлементов;
        int FirstDeleted = -1;
        static SpinLock sl = new SpinLock();
        public int Add(AutoWrap Объект)
        {



            var элемент = new ЭлементХранилища(Объект);

            var gotLock = false;
            try
            {
                sl.Enter(ref gotLock);


                if (FirstDeleted == -1)
                {
                    
                    return AddInArray(элемент);
                }
                else
                {
                    int newPos = FirstDeleted;
                    FirstDeleted = Элементы[newPos].Next;
                    Элементы[newPos] = элемент;
                    return newPos;

                }
            }
            finally
            {
                 if (gotLock) sl.Exit();
            }

        }

        int AddInArray(ЭлементХранилища Элемент)
        {

               if (КоличествоЭлементов == РазмерМассива)
                {
                    var temp = new ЭлементХранилища[РазмерМассива * 2];
                    Array.Copy(Элементы, 0, temp, 0, Элементы.Length);
                    Элементы = temp;
                    РазмерМассива = Элементы.Length;

                }

                Элементы[КоличествоЭлементов] = Элемент;
                var res = КоличествоЭлементов;
                КоличествоЭлементов++;
                return res;
                   
        }
        public void RemoveKey(int Pos)
        {
            var элементы = Элементы;
            // Первый элемнт никогда не удаляем.
            if (Pos > 0 && Pos < элементы.Length && элементы[Pos].Объект != null)
            {
                var gotLock = false;
                try
                {
                    sl.Enter(ref gotLock);

                    var Элемент = new ЭлементХранилища(null, FirstDeleted);
                    Элементы[Pos] = Элемент;

                    FirstDeleted = Pos;
                }

                finally
                {
                   if (gotLock) sl.Exit();
                }
            }



        }

        public AutoWrap GetValue(int Pos)
        {
        
          // По идее для получения элемента не нужно никаких блокировок
          // Получает текущий массив элеменов
            var элементы = Элементы;
            if (!(Pos > -1 && Pos < элементы.Length && элементы[Pos].Объект != null))
                return null;

            return элементы[Pos].Объект;

        }

    }



Основное изменение массива происходит только при изменении размера массива



if (КоличествоЭлементов == РазмерМассива)
                {
                    var temp = new ЭлементХранилища[РазмерМассива * 2];
                    Array.Copy(Элементы, 0, temp, 0, Элементы.Length);
                    Элементы = temp;
                    РазмерМассива = Элементы.Length;

                }



Доступ к элементам массива по идее можно делать без блокировок



public AutoWrap GetValue(int Pos)
        {
        
          // По идее для получения элемента не нужно никаких блокировок
          // Получает текущий массив элементов
            var элементы = Элементы;
            if (!(Pos > -1 && Pos < элементы.Length && элементы[Pos].Объект != null))
                return null;

            return элементы[Pos].Объект;

        }
и солнце б утром не вставало, когда бы не было меня
Re[2]: .Net Core. Вызов манагед кода из натива
От: vorona  
Дата: 08.08.16 09:30
Оценка:
Здравствуйте, Serginio1, Вы писали:

Запись можно сделать:
Interlocked.CompareExchange(ref Элементы, temp, Элементы);


Чтение:
Interlocked.CompareExchange(ref Элементы, null, null);


РазмерМассива:
int РазмерМассива => Элементы.Length;
Re[3]: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 08.08.16 09:40
Оценка:
Здравствуйте, vorona, Вы писали:

V>Здравствуйте, Serginio1, Вы писали:


V>Запись можно сделать:

V>
V>Interlocked.CompareExchange(ref Элементы, temp, Элементы);
V>


V>Чтение:

V>
V>Interlocked.CompareExchange(ref Элементы, null, null);
V>


V>РазмерМассива:

V>
V>int РазмерМассива => Элементы.Length;
V>


Спасибо! Тогда SpinLock не нужен? Ладно попозже сделаю.

То есть вместо

 var элементы = Элементы;


Преедпочтительнее


var элементы = Interlocked.CompareExchange(ref Элементы, null, null);
и солнце б утром не вставало, когда бы не было меня
Re: .Net Core. Вызов манагед кода из натива
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 09.08.16 09:13
Оценка:
Здравствуйте, Serginio1, Вы писали:
Выложил статьи
Разработка → Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux
Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux
Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux II
Асинхронное программирование в 1С через .Net Native ВК


Исходники здесь
и солнце б утром не вставало, когда бы не было меня
Re: 1С,Linux,Excel,Word,OpenXML,Net Core
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 22.08.16 11:12
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>1С,Linux,Excel,Word,OpenXML,Net Core


S>Исходники здесь
и солнце б утром не вставало, когда бы не было меня
Re: Ошибка ucrtbase.dll Недопустимый параметр был передан фу
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 30.08.16 08:52
Оценка:
Здравствуйте, Serginio1, Вы писали:

Суть такая из натива вызываем статические методы .Net библиотеки.
Под 32 разрядными dll и exe все прекрасно.

Скомпилировал под 64 разрядное. Если запускать из экзешника
То все нормально. Но если из 64 разрядной 1С 8.3.9

Выдает ошибку

Необработанное исключение по адресу 0x00007FFD76FB8528 (ucrtbase.dll) в 1cv8.exe: Недопустимый параметр был передан функции, для которой недопустимые параметры вызывают неустранимую ошибку.

и солнце б утром не вставало, когда бы не было меня
Отредактировано 19.09.2016 8:48 Serginio1 . Предыдущая версия . Еще …
Отредактировано 19.09.2016 8:46 Serginio1 . Предыдущая версия .
Отредактировано 19.09.2016 8:21 Serginio1 . Предыдущая версия .
Re[2]: Ошибка ucrtbase.dll Недопустимый параметр был передан функции
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 30.08.16 10:47
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S> Суть такая из натива вызываем статические методы .Net библиотеки.

S>Под 32 разрядными dll и exe все прекрасно.

S>Скомпилировал под 64 разрядное. Если запускать из экзешника

S>То все нормально. Но если из 64 разрядной 1С 8.3.9

Возможно ошибка из-за рефакторинга
https://msdn.microsoft.com/ru-ru/library/bb531344.aspx


Библиотека времени выполнения C (CRT)
Общие изменения
•Двоичные файлы, полученные в результате рефакторинга

Был осуществлен рефакторинг библиотеки CRT, в результате чего она была разделена на два разных двоичных файла — универсальный CRT (ucrtbase), который содержит большинство стандартных функциональных возможностей, и библиотеку времени выполнения VC (vcruntime140), которая содержит функции, связанные с компилятором, такие как обработка исключений и встроенные функции. В случае использования параметров проекта по умолчанию это изменение вас не затронет, так как компоновщик будет автоматически использовать новые библиотеки по умолчанию. Если вы установили для свойства Игнорировать все стандартные библиотекикомпоновщика в проекте значение Да или используете параметр компоновщика /NODEFAULTLIB в командной строке, необходимо обновить список библиотек (в свойстве Дополнительные зависимости), чтобы включить в него новые подвергнутые рефакторингу библиотеки. Замените старую библиотеку CRT (libcmt.lib, libcmtd.lib, msvcrt.lib, msvcrtd.lib) эквивалентными подвергнутыми рефакторингу библиотеками. Для каждой из двух подвергнутых рефакторингу библиотек существует статическая (.lib) и динамическая (.dll) версии, а также версия выпуска (без суффикса) и отладочная версия (с суффиксом "d"). Динамические версии имеют библиотеку импорта, с которой выполняется связь. Рефакторингу подвергнуты две библиотеки: универсальная CRT (а именно ucrtbase.dll или ucrtbase.lib, ucrtbased.dll или ucrtbased.lib) и библиотека времени выполнения VC — libvcruntime.lib, libvcruntime.dll, libvcruntimed.lib и libvcruntimed.dll. См. раздел Особенности библиотеки CRT.

и солнце б утром не вставало, когда бы не было меня
Re[2]: Ошибка ucrtbase.dll Недопустимый параметр был передан
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 01.09.16 09:02
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S> Суть такая из натива вызываем статические методы .Net библиотеки.

S>Под 32 разрядными dll и exe все прекрасно.

S>Скомпилировал под 64 разрядное. Если запускать из экзешника

S>То все нормально. Но если из 64 разрядной 1С 8.3.9


Вот Стек

ucrtbase.dll!_invoke_watson() Нет данных
ucrtbase.dll!_invalid_parameter() Нет данных
ucrtbase.dll!_invalid_parameter_noinfo() Нет данных
ucrtbase.dll!_setmode() Нет данных
clrjit.dll!jitStartup() Нет данных
coreclr.dll!EEJitManager::SetCpuInfo(void) Нет данных
coreclr.dll!EEJitManager::LoadJIT(void) Нет данных
coreclr.dll!UnsafeJitFunction(class MethodDesc *,class COR_ILMETHOD_DECODER *,unsigned long,unsigned long,unsigned long *) Нет данных
coreclr.dll!MethodDesc::MakeJitWorker(class COR_ILMETHOD_DECODER *,unsigned long,unsigned long) Нет данных
coreclr.dll!MethodDesc::DoPrestub(class MethodTable *) Нет данных
coreclr.dll!PreStubWorker() Нет данных
coreclr.dll!ThePreStub() Нет данных
coreclr.dll!UMThunkStub() Нет данных
> AddInNetObjectToNative64.dll!NetObjectToNative::ManagedDomainLoader::CreateManagedDomain(NetObjectToNative::CoreClrStartParams * pCoreClrStartupParams)Строка 128 C++



В новой версии .Net Core 1.0.1
https://blogs.msdn.microsoft.com/dotnet/2016/09/13/announcing-september-2016-updates-for-net-core-1-0/

Исправили ошибку

https://github.com/dotnet/coreclr/issues/6460

In Jitstartup, JIT creates a file descriptor for stdout and unconditionally passes it to setmode, without checking for failures. This happens at https://github.com/dotnet/coreclr/blob/ee680783778ed0abb186ae41a8c861d5cdcadccd/src/jit/ee_il_dll.cpp#L76.

Failure to check for invalid descriptors can result in setmode triggering failfast.


Сейчас все без ошибок
и солнце б утром не вставало, когда бы не было меня
Отредактировано 19.09.2016 8:45 Serginio1 . Предыдущая версия . Еще …
Отредактировано 19.09.2016 8:19 Serginio1 . Предыдущая версия .
Re[2]: Ошибка ucrtbase.dll Недопустимый параметр был передан фу
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 19.09.16 08:46
Оценка: 24 (1)
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S> Суть такая из натива вызываем статические методы .Net библиотеки.

S>Под 32 разрядными dll и exe все прекрасно.

S>Скомпилировал под 64 разрядное. Если запускать из экзешника

S>То все нормально. Но если из 64 разрядной 1С 8.3.9


В новой версии .Net Core 1.0.1
https://blogs.msdn.microsoft.com/dotnet/2016/09/13/announcing-september-2016-updates-for-net-core-1-0/

Исправили ошибку

https://github.com/dotnet/coreclr/issues/6460

In Jitstartup, JIT creates a file descriptor for stdout and unconditionally passes it to setmode, without checking for failures. This happens at https://github.com/dotnet/coreclr/blob/ee680783778ed0abb186ae41a8c861d5cdcadccd/src/jit/ee_il_dll.cpp#L76.

Failure to check for invalid descriptors can result in setmode triggering failfast.


Сейчас все без ошибок
и солнце б утром не вставало, когда бы не было меня
Re: Виртуальгые машины.Обмен по Tcp/IP
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 25.09.16 07:32
Оценка:
Можно ли под машиной запустить Windows и Linux. Под Windows считывать данные и передавать их в приложения под Linux по TCP/IP

Под многое оборудование для Linux нет драйверов. Но вот хотел узнать про виртуальные машины. Можно держать Linux и Windows и обмениваться по TCP/IP.
Сейчас пишу статью по кроосплатформенному применению .Net Core в 1С и обмену по Tcp/IP между различными устройствами.И нужны примеры применения
и солнце б утром не вставало, когда бы не было меня
Re[2]: Виртуальгые машины.Обмен по Tcp/IP
От: _Raz_  
Дата: 25.09.16 07:51
Оценка: 24 (1)
Здравствуйте, Serginio1, Вы писали:

S>Можно ли под машиной запустить Windows и Linux. Под Windows считывать данные и передавать их в приложения под Linux по TCP/IP

S>Под многое оборудование для Linux нет драйверов. Но вот хотел узнать про виртуальные машины. Можно держать Linux и Windows и обмениваться по TCP/IP.

На все вопросы — да.

Networking in VirtualBox
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.