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 . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.