Здравствуйте, Serginio1, Вы писали:
S> Передавать статические функции или ThisCall трудоемко.
Что значит передавать? Откуда-куда?
S>Проще общаться с нативом в разные стороны через абстрактные классы
Вот как раз и не проще. Иногда проще через очень даже непрозрачные структуры, где клиент и сервер знает её внутренности. Вообще зависит, от того с какой стороны смотреть и/или какие проблемы решаются. Иногда гораздо проще opaque pointer + вся работа только через статические функции (импорты из длл).
И тут весь этот бред вокруг IUnknown я считаю лишним абсолютно. Далеко не проще через абстрактные.
Я ещё раз делаю акцент: решение зависит только от входящих требований: стабильное ABI, простое, C-совместимое, с или без символическим связыванием имен, пишем ли мы и клиент и сервер и т.п.
S> Так суть интерфейса это VMT. А классы с виртуальными методами кроссплатформенны. S> В 1С это прекрасно работает
Мне показалось, что в другой ветке же ж разобрались как можно заставить эту кухню работать?
Re[13]: .Net Core Вызов виртуальных методов нативных объекто
Здравствуйте, fddima, Вы писали:
F>Здравствуйте, Serginio1, Вы писали:
S>> Передавать статические функции или ThisCall трудоемко. F> Что значит передавать? Откуда-куда?
Из натива в .Net Native вестимо http://rsdn.org/forum/dotnet/6609566.1
S>>Проще общаться с нативом в разные стороны через абстрактные классы F> Вот как раз и не проще. Иногда проще через очень даже непрозрачные структуры, где клиент и сервер знает её внутренности. Вообще зависит, от того с какой стороны смотреть и/или какие проблемы решаются. Иногда гораздо проще opaque pointer + вся работа только через статические функции (импорты из длл).
F> И тут весь этот бред вокруг IUnknown я считаю лишним абсолютно. Далеко не проще через абстрактные.
F> Я ещё раз делаю акцент: решение зависит только от входящих требований: стабильное ABI, простое, C-совместимое, с или без символическим связыванием имен, пишем ли мы и клиент и сервер и т.п.
S>> Так суть интерфейса это VMT. А классы с виртуальными методами кроссплатформенны. S>> В 1С это прекрасно работает F> Мне показалось, что в другой ветке же ж разобрались как можно заставить эту кухню работать?
Да все это работает и на уровне статических методов (ThisCall суть таже). При использовании IUnknown идет куча ненужных вызовов.
Кроме того я хочу эти абстрактные C++ классы с stdcall вызовами использовать в .Net Core
Там мне приходится передавать ссылки на каждый метод.
Но хотоелось бы аналогов интерфейсов. При этом использовать только ссылку на объект, первым полем которого является ссылка на VMT.
Это просто удобнее при описании и при выполнении.
и солнце б утром не вставало, когда бы не было меня
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
internal delegate void ВиртуальныйМетодОбъектаСDelegate(IntPtr self, int Число);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
internal delegate void ВиртуальныйМетодОбъекта2Delegate(IntPtr self, int Число1, int Число2);
Создал функцию для получения адреса метода
public static IntPtr ПолучитьАдресВиртуальногоМетода(IntPtr Объект, int ИндексВТаблицеВиртуальныхМетодов )
{
int размерIntPtr = Marshal.SizeOf<IntPtr>();
// Первым полем объекта идет ссылка на VMT
// Прочитаем еёvar АдресVMT = Marshal.ReadIntPtr(Объект);
// получим адресс метода по смещению в VMTvar АдресМетодаVMT = АдресVMT + ИндексВТаблицеВиртуальныхМетодов * размерIntPtr;
var АдресМетода = Marshal.ReadIntPtr(АдресМетодаVMT);
return АдресМетода;
}
Для интерфеса вроде работает
public static void CallInterface(IntPtr cb)
{
var cb2 = Marshal.GetObjectForIUnknown(cb) as ICallback;
cb2?.execute(555);
// метод execute в VMT идет 4 (QueryInterface,Addref,Release)
// а индекс равен 3 var АдресМетода = ПолучитьАдресВиртуальногоМетода(cb,3);
// Получим делегат по дресуvar execute = Marshal.GetDelegateForFunctionPointer<ВиртуальныйМетодОбъектаСDelegate>(АдресМетода);
// И вызовем метод
execute(cb, 666);
}
Надо будет с параметрами проверить.
Но вот с ThisCall проблема.
Здравствуйте, Serginio1, Вы писали:
S> Так суть интерфейса это VMT. А классы с виртуальными методами кроссплатформенны.
Выделенное в общем случае неверно, тебе уже несколько раз об этом сказали, и зависит от используемого компилятора и ABI который он использует для бинарного представления (vtable layout) виртуальных методов (явных- указанных в описании класса, и не только — добавляемых компилятором) класса для целевой (там где будет выполняться код) платформы.
Конкретно: популярные компиляторы C++ vc/gcc/clang используют след. ABI:
vc/windows — Windows ABI
gcc (начиная с какой-то версии)/linux — Itanium ABI
clang — на windows — Windows ABI ,на linux — Itanium ABI.
В Windows ABI описание класса с чисто-виртуальными функциями (интерфейс) в точности соотв. структуре с указателем на таблицу содержащую указатели на методы — основа COM:
C++ :
The virtual table contains offset-to-top and RTTI fields followed by virtual function pointers. There is one function pointer entry for each virtual function declared in the class, in declaration order, with any implicitly-defined virtual destructor pair last.
Соотв. если делать ручной маршалинг, все это нужно учитывать.
S> Но при что бы получить ссылку на интерфейс, вызывается куча QueryInterface, AddRef и Release
Здравствуйте, Serginio1, Вы писали:
S>Попробовал с VMT S>Определил методы
Вот ты неуемный ты бы для начала проверил, работает ли COM-интероп на linux — ведь это же твоя цель?
И если работает — тему можно закрывать, COM-интеропа тебе хватит за глаза.
Или ты заради любви к искусству?
S>
S> [UnmanagedFunctionPointer(CallingConvention.Winapi)]
S> internal delegate void ВиртуальныйМетодОбъектаСDelegate(IntPtr self, int Число);
S> [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
S> internal delegate void ВиртуальныйМетодОбъекта2Delegate(IntPtr self, int Число1, int Число2);
S>
CallingConvention.Winapi — тот же stdcall
CallingConvention.ThisCall — зачем тебе это?
S> Создал функцию для получения адреса метода
S>
S> public static IntPtr ПолучитьАдресВиртуальногоМетода(IntPtr Объект, int ИндексВТаблицеВиртуальныхМетодов )
S> {
S> int размерIntPtr = Marshal.SizeOf<IntPtr>();
S> // Первым полем объекта идет ссылка на VMT
S> // Прочитаем её
S> var АдресVMT = Marshal.ReadIntPtr(Объект);
S> // получим адресс метода по смещению в VMT
S> var АдресМетодаVMT = АдресVMT + ИндексВТаблицеВиртуальныхМетодов * размерIntPtr;
S> var АдресМетода = Marshal.ReadIntPtr(АдресМетодаVMT);
S> return АдресМетода;
S> }
тебе намекал, а ты сделал вид что понял весь хардкор с Marshal.ReadIntPtr за тебя сделает рантайм.
S> параметры поменяны местами, а переданное первым параметром значение не соотвествует переданному.
Используй stdcall как в native коде, так и в делегате на C#, и все будет норм.
Re[15]: .Net Core Вызов виртуальных методов нативных объекто
Здравствуйте, pilgrim_, Вы писали:
_>Здравствуйте, Serginio1, Вы писали:
S>>Попробовал с VMT S>>Определил методы
_>Вот ты неуемный ты бы для начала проверил, работает ли COM-интероп на linux — ведь это же твоя цель? _>И если работает — тему можно закрывать, COM-интеропа тебе хватит за глаза. _>Или ты заради любви к искусству?
И то и другое. Да ине нужны мне методы IUknown. Я итак передаю нужныю ссылку, а подсчет ссылок если мне нужно организую сам.
S>> [UnmanagedFunctionPointer(CallingConvention.Winapi)]
S>> internal delegate void ВиртуальныйМетодОбъектаСDelegate(IntPtr self, int Число);
S>> [UnmanagedFunctionPointer(CallingConvention.ThisCall)]
S>> internal delegate void ВиртуальныйМетодОбъекта2Delegate(IntPtr self, int Число1, int Число2);
S>>
_>CallingConvention.Winapi — тот же stdcall _>CallingConvention.ThisCall — зачем тебе это?
Вот CallingConvention.ThisCall то работает для
struct TestThisCall {
public:
virtual int execute(int value1, int value2);
};
S>> Создал функцию для получения адреса метода
S>>
S>> public static IntPtr ПолучитьАдресВиртуальногоМетода(IntPtr Объект, int ИндексВТаблицеВиртуальныхМетодов )
S>> {
S>> int размерIntPtr = Marshal.SizeOf<IntPtr>();
S>> // Первым полем объекта идет ссылка на VMT
S>> // Прочитаем её
S>> var АдресVMT = Marshal.ReadIntPtr(Объект);
S>> // получим адресс метода по смещению в VMT
S>> var АдресМетодаVMT = АдресVMT + ИндексВТаблицеВиртуальныхМетодов * размерIntPtr;
S>> var АдресМетода = Marshal.ReadIntPtr(АдресМетодаVMT);
S>> return АдресМетода;
S>> }
тебе намекал, а ты сделал вид что понял весь хардкор с Marshal.ReadIntPtr за тебя сделает рантайм.
S>> параметры поменяны местами, а переданное первым параметром значение не соотвествует переданному.
_>Используй stdcall как в native коде, так и в делегате на C#, и все будет норм.
Проблема в том, что ThisCall и stdcall не совместимы.
То есть я должен определить как
virtual int execute(int value1, int value2);
и солнце б утром не вставало, когда бы не было меня
Здравствуйте, Serginio1, Вы писали:
S>Здравствуйте, pilgrim_, Вы писали:
_>>Здравствуйте, Serginio1, Вы писали:
S>>>Попробовал с VMT S>>>Определил методы
_>>Вот ты неуемный ты бы для начала проверил, работает ли COM-интероп на linux — ведь это же твоя цель? _>>И если работает — тему можно закрывать, COM-интеропа тебе хватит за глаза. _>>Или ты заради любви к искусству?
S> И то и другое. Да ине нужны мне методы IUknown. Я итак передаю нужныю ссылку, а подсчет ссылок если мне нужно организую сам.
Не забывай про связку native -> managed iface, временем жизни managed объекта на стороне managed тоже ручками придется управлять.
S> Для приведения к интерфейсу при вызове одного метода идет куча QueryInterface Addref,Release S>http://rsdn.org/forum/dotnet/6611240.1
_>>CallingConvention.Winapi — тот же stdcall _>>CallingConvention.ThisCall — зачем тебе это?
S> Вот CallingConvention.ThisCall то работает для
_>Используй stdcall как в native коде, так и в делегате на C#, и все будет норм.
S> Проблема в том, что ThisCall и stdcall не совместимы.
Внимательно смотри выделенное, stdcall (как и cdecl) — это C-стандарт соглашений о вызове, с одинаковой реализацией разными компиляторами,
тогда как thiscall — compiler specific — https://en.wikipedia.org/wiki/X86_calling_conventions#thiscall .
Тебя все еще интересует linux?
Re[17]: .Net Core Вызов виртуальных методов нативных объекто
S>> Проблема в том, что ThisCall и stdcall не совместимы.
_>Внимательно смотри выделенное, stdcall (как и cdecl) — это C-стандарт соглашений о вызове, с одинаковой реализацией разными компиляторами, _>тогда как thiscall — compiler specific — https://en.wikipedia.org/wiki/X86_calling_conventions#thiscall . _>Тебя все еще интересует linux?
Да волнует. Но компилятор у меня будет один. Опять же я тебе давал ссылку на структуры применяемые в 1С.
Там используется виртуальные методы stdcall.
А вот как это в .Net использовать?
Кстати объявив метод
[UnmanagedFunctionPointer(CallingConvention.Winapi)]
internal delegate void ВиртуальныйМетодОбъектаСDelegate(IntPtr self, int Число);
У меня метод вызвался как ThisCall по stdcall
public static void CallInterface(IntPtr cb)
{
var cb2 = Marshal.GetObjectForIUnknown(cb) as ICallback;
cb2?.execute(555);
// метод execute в VMT идет 4 (QueryInterface,Addref,Release)
// а индекс равен 3 var АдресМетода = ПолучитьАдресВиртуальногоМетода(cb,3);
// Получим делегат по дресуvar execute = Marshal.GetDelegateForFunctionPointer<ВиртуальныйМетодОбъектаСDelegate>(АдресМетода);
// И вызовем метод
execute(cb, 666);
}
То есть первый параметр пошел в регисты. Сейчас проверю с несколькими параметрами
и солнце б утром не вставало, когда бы не было меня
_>>Здравствуйте, Serginio1, Вы писали: S>>>Попробовал с VMT S>>>Определил методы _>>Вот ты неуемный ты бы для начала проверил, работает ли COM-интероп на linux — ведь это же твоя цель? _>>И если работает — тему можно закрывать, COM-интеропа тебе хватит за глаза. _>>Или ты заради любви к искусству? S> И то и другое. Да ине нужны мне методы IUknown. Я итак передаю нужныю ссылку, а подсчет ссылок если мне нужно организую сам. S> Для приведения к интерфейсу при вызове одного метода идет куча QueryInterface Addref,Release S>http://rsdn.org/forum/dotnet/6611240.1
Здравствуйте, pilgrim_, Вы писали:
Спасибо!
Я вот только непонял, почему при stdcall первый параметр идет в регистры?
Или this при stdcall идет первым параметром?
Здравствуйте, pilgrim_, Вы писали:
_>Здравствуйте, Serginio1, Вы писали:
S>> Я вот только непонял, почему при stdcall первый параметр идет в регистры?
_>Не идет, все через стэк, справа-налево — https://en.wikipedia.org/wiki/X86_calling_conventions#stdcall
Спасибо! Вот под старость лет узнал Еще раз огромное Спасибо!
и солнце б утром не вставало, когда бы не было меня
Re[20]: .Net Core Вызов виртуальных методов нативных объекто
Здравствуйте, Serginio1, Вы писали: S> Спасибо! Вот под старость лет узнал Еще раз огромное Спасибо!
Не за что, посмотри еще вот это — https://github.com/mono/CppSharp , по описанию мощная штука, проверил — не без нюансов, но работает!
Позволяет вмешиваться в процесс генерации interop-кода.
public unsafe abstract partial class ICallbackNotCom : IDisposable
{
[StructLayout(LayoutKind.Explicit, Size = 4)]
public partial struct __Internal
{
[FieldOffset(0)]
public global::System.IntPtr vfptr_ICallbackNotCom;
//[SuppressUnmanagedCodeSecurity]
//[DllImport("NotComCallback.Native.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall,
// EntryPoint="??0ICallbackNotCom@@QAE@XZ")]
//internal static extern global::System.IntPtr ctor_0(global::System.IntPtr instance);
//[SuppressUnmanagedCodeSecurity]
//[DllImport("NotComCallback.Native.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall,
// EntryPoint="??0ICallbackNotCom@@QAE@ABV0@@Z")]
//internal static extern global::System.IntPtr cctor_1(global::System.IntPtr instance, global::System.IntPtr _0);
}
public global::System.IntPtr __Instance { get; protected set; }
protected int __PointerAdjustment;
public static readonly System.Collections.Concurrent.ConcurrentDictionary<IntPtr, ICallbackNotCom> NativeToManagedMap = new System.Collections.Concurrent.ConcurrentDictionary<IntPtr, ICallbackNotCom>();
protected void*[] __OriginalVTables;
protected bool __ownsNativeInstance;
public static ICallbackNotCom __CreateInstance(global::System.IntPtr native, bool skipVTables = false)
{
return new ICallbackNotComInternal(native.ToPointer(), skipVTables);
}
public static ICallbackNotCom __CreateInstance(ICallbackNotCom.__Internal native, bool skipVTables = false)
{
return new ICallbackNotComInternal(native, skipVTables);
}
protected ICallbackNotCom(void* native, bool skipVTables = false)
{
if (native == null)
return;
__Instance = new global::System.IntPtr(native);
__OriginalVTables = new void*[] { ((__Internal*) native)->vfptr_ICallbackNotCom.ToPointer() };
}
protected ICallbackNotCom()
{
__Instance = Marshal.AllocHGlobal(4);
__ownsNativeInstance = true;
NativeToManagedMap[__Instance] = this;
//__Internal.ctor_0((__Instance + __PointerAdjustment));
SetupVTables(GetType().FullName == "NotComCallback.ICallbackNotCom");
}
protected ICallbackNotCom(ICallbackNotCom _0)
{
__Instance = Marshal.AllocHGlobal(4);
__ownsNativeInstance = true;
NativeToManagedMap[__Instance] = this;
if (ReferenceEquals(_0, null))
throw new global::System.ArgumentNullException("_0", "Cannot be null because it is a C++ reference (&).");
var __arg0 = _0.__Instance;
//__Internal.cctor_1((__Instance + __PointerAdjustment), __arg0);
SetupVTables(GetType().FullName == "NotComCallback.ICallbackNotCom");
}
public void Dispose()
{
Dispose(disposing: true);
}
public virtual void Dispose(bool disposing)
{
ICallbackNotCom __dummy;
NativeToManagedMap.TryRemove(__Instance, out __dummy);
((__Internal*) __Instance)->vfptr_ICallbackNotCom = new global::System.IntPtr(__OriginalVTables[0]);
if (__ownsNativeInstance)
Marshal.FreeHGlobal(__Instance);
}
public abstract bool Execute();
public abstract bool Dispatch(ICallbackNotCom other);
public abstract bool Release
{
get;
}
#region Virtual table interop
// bool __stdcall release() = 0private static Delegates.Func_bool_IntPtr _Release_0DelegateInstance;
private static bool _Release_0DelegateHook(global::System.IntPtr instance)
{
if (!NativeToManagedMap.ContainsKey(instance))
throw new global::System.Exception("No managed instance was found");
var __target = (ICallbackNotCom) NativeToManagedMap[instance];
if (__target.__ownsNativeInstance)
__target.SetupVTables();
var __ret = __target.Release;
return __ret;
}
// bool __stdcall execute() = 0private static Delegates.Func_bool_IntPtr _Execute_0DelegateInstance;
private static bool _Execute_0DelegateHook(global::System.IntPtr instance)
{
if (!NativeToManagedMap.ContainsKey(instance))
throw new global::System.Exception("No managed instance was found");
var __target = (ICallbackNotCom) NativeToManagedMap[instance];
if (__target.__ownsNativeInstance)
__target.SetupVTables();
var __ret = __target.Execute();
return __ret;
}
// bool __stdcall dispatch(ICallbackNotCom* other) = 0private static Delegates.Func_bool_IntPtr_IntPtr _Dispatch_0DelegateInstance;
private static bool _Dispatch_0DelegateHook(global::System.IntPtr instance, global::System.IntPtr other)
{
if (!NativeToManagedMap.ContainsKey(instance))
throw new global::System.Exception("No managed instance was found");
var __target = (ICallbackNotCom) NativeToManagedMap[instance];
if (__target.__ownsNativeInstance)
__target.SetupVTables();
ICallbackNotCom __result0;
if (other == IntPtr.Zero) __result0 = null;
else if (ICallbackNotCom.NativeToManagedMap.ContainsKey(other))
__result0 = (ICallbackNotCom) ICallbackNotCom.NativeToManagedMap[other];
else __result0 = ICallbackNotCom.__CreateInstance(other);
var __ret = __target.Dispatch(__result0);
return __ret;
}
private static void*[] __ManagedVTables;
private static void*[] _Thunks;
private void SetupVTables(bool destructorOnly = false)
{
if (__OriginalVTables != null)
return;
var native = (__Internal*) __Instance.ToPointer();
__OriginalVTables = new void*[] { ((__Internal*) native)->vfptr_ICallbackNotCom.ToPointer() };
if (destructorOnly)
return;
if (_Thunks == null)
{
_Thunks = new void*[3];
_Release_0DelegateInstance += _Release_0DelegateHook;
_Thunks[0] = Marshal.GetFunctionPointerForDelegate(_Release_0DelegateInstance).ToPointer();
_Execute_0DelegateInstance += _Execute_0DelegateHook;
_Thunks[1] = Marshal.GetFunctionPointerForDelegate(_Execute_0DelegateInstance).ToPointer();
_Dispatch_0DelegateInstance += _Dispatch_0DelegateHook;
_Thunks[2] = Marshal.GetFunctionPointerForDelegate(_Dispatch_0DelegateInstance).ToPointer();
}
if (__ManagedVTables == null)
{
__ManagedVTables = new void*[1];
var vfptr0 = Marshal.AllocHGlobal(3 * 4);
__ManagedVTables[0] = vfptr0.ToPointer();
*(void**)(vfptr0 + 0) = _Thunks[0];
*(void**)(vfptr0 + 4) = _Thunks[1];
*(void**)(vfptr0 + 8) = _Thunks[2];
}
native->vfptr_ICallbackNotCom = new IntPtr(__ManagedVTables[0]);
}
#endregion
}
public unsafe partial class ICallbackNotComInternal : ICallbackNotCom, IDisposable
{
private static void* __CopyValue(ICallbackNotCom.__Internal native)
{
var ret = Marshal.AllocHGlobal(4);
*(ICallbackNotCom.__Internal*) ret = native;
return ret.ToPointer();
}
internal ICallbackNotComInternal(ICallbackNotCom.__Internal native, bool skipVTables = false)
: this(__CopyValue(native), skipVTables)
{
__ownsNativeInstance = true;
NativeToManagedMap[__Instance] = this;
}
internal ICallbackNotComInternal(void* native, bool skipVTables = false)
: base((void*) null)
{
__PointerAdjustment = 0;
__Instance = new global::System.IntPtr(native);
__OriginalVTables = new void*[] { ((__Internal*) native)->vfptr_ICallbackNotCom.ToPointer() };
}
public override bool Execute()
{
var __slot = *(void**) ((IntPtr) __OriginalVTables[0] + 1 * 4);
var ___Execute_0Delegate = (Delegates.Func_bool_IntPtr) Marshal.GetDelegateForFunctionPointer(new IntPtr(__slot), typeof(Delegates.Func_bool_IntPtr));
var __ret = ___Execute_0Delegate((__Instance + __PointerAdjustment));
return __ret;
}
public override bool Dispatch(ICallbackNotCom other)
{
var __slot = *(void**) ((IntPtr) __OriginalVTables[0] + 2 * 4);
var ___Dispatch_0Delegate = (Delegates.Func_bool_IntPtr_IntPtr) Marshal.GetDelegateForFunctionPointer(new IntPtr(__slot), typeof(Delegates.Func_bool_IntPtr_IntPtr));
var __arg0 = ReferenceEquals(other, null) ? global::System.IntPtr.Zero : other.__Instance;
var __ret = ___Dispatch_0Delegate((__Instance + __PointerAdjustment), __arg0);
return __ret;
}
public override bool Release
{
get
{
var __slot = *(void**) ((IntPtr) __OriginalVTables[0] + 0 * 4);
var ___Release_0Delegate = (Delegates.Func_bool_IntPtr) Marshal.GetDelegateForFunctionPointer(new IntPtr(__slot), typeof(Delegates.Func_bool_IntPtr));
var __ret = ___Release_0Delegate((__Instance + __PointerAdjustment));
return __ret;
}
}
}
public unsafe partial class NotComCallback
{
public partial struct __Internal
{
[SuppressUnmanagedCodeSecurity]
[DllImport("NotComCallback.Native.dll", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.StdCall,
EntryPoint="_UnmanagedWrapCallbackNotCom@4")]
internal static extern global::System.IntPtr UnmanagedWrapCallbackNotCom_0(global::System.IntPtr other);
}
public static ICallbackNotCom UnmanagedWrapCallbackNotCom(ICallbackNotCom other)
{
var __arg0 = ReferenceEquals(other, null) ? global::System.IntPtr.Zero : other.__Instance;
var __ret = __Internal.UnmanagedWrapCallbackNotCom_0(__arg0);
ICallbackNotCom __result0;
if (__ret == IntPtr.Zero) __result0 = null;
else if (ICallbackNotCom.NativeToManagedMap.ContainsKey(__ret))
__result0 = (ICallbackNotCom) ICallbackNotCom.NativeToManagedMap[__ret];
else __result0 = ICallbackNotCom.__CreateInstance(__ret);
return __result0;
}
}
namespace Delegates
{
[SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointerAttribute(global::System.Runtime.InteropServices.CallingConvention.StdCall)]
public unsafe delegate bool Func_bool_IntPtr(global::System.IntPtr instance);
[SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointerAttribute(global::System.Runtime.InteropServices.CallingConvention.StdCall)]
public unsafe delegate bool Func_bool_IntPtr_IntPtr(global::System.IntPtr instance, global::System.IntPtr arg1);
}
Все работает как полагается.
ps: я закоментарил только импорт/вызовы ctor, т.к. не импортирую их. вероятно этим можно управлять в процессе генерации интероп-кода. + из метода bool __stdcall release() = 0 почему то сделала get-свойство Release.