Сообщение Re[13]: Приоритет вызова перегруженных методов от 22.06.2016 7:22
Изменено 22.06.2016 7:30 Serginio1
Здравствуйте, Serginio1, Вы писали:
Добавил простенький список для хранения объектов
Создал класс обертку
Экспортируются функции
На С++ выглядит так
Думаю статью написать. Как для C++ лучше сделать обертку. Для 1С думаю доделать на этой неделе
Добавил простенький список для хранения объектов
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);
}
На С++ выглядит так
// Загрузим 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"Новая Строка";
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С думаю доделать на этой неделе
Здравствуйте, Serginio1, Вы писали:
Добавил простенький список для хранения объектов
Создал класс обертку
Экспортируются функции
На С++ выглядит так
Думаю статью написать. Как для C++ лучше сделать обертку. Для 1С думаю доделать на этой неделе
Добавил простенький список для хранения объектов
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);
}
На С++ выглядит так
// Загрузим 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С думаю доделать на этой неделе