Я работаю с неуправляемым ресурсом с C #.Ресурс предоставляет обратный вызов, который можно настроить для определенных событий, которые могут произойти в оборудовании.Чтобы получить доступ к неуправляемым функциям, я делаю следующее:
[DllImportAttribute("testDLL.dll", EntryPoint = "InstallCallback")]
public static extern short InstallCallback(uint handle, byte x, byte y, IntFuncPtr ptr);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void IntFuncPtr(uint handle, byte x, byte y, LogEntry info);
Сначала я устанавливаю обратный вызов со ссылкой на метод, который следует за делегатом IntFuncPtr.Затем я позволил аппаратному обеспечению сделать свое дело.После примерно 4700 вызовов обратного вызова приложение вылетает.Обратный вызов работает нормально, если я пишу код на языке c / c ++, однако я могу воспроизвести его, удалив __stdcall из моей функции обратного вызова.Из C # я не могу поймать ошибку, которая указывает, что приложение умирает в неуправляемом ресурсе.С приложением c / c ++ я вижу, что стек переполняется без __stdcall.
Я подумал, что делегат может не работать с соглашением о вызовах stdcall, поэтому я попробовал следующее:
[DllImportAttribute("testDLL.dll", EntryPoint = "InstallCallback")]
public static extern short InstallCallback(uint handle, byte x, byte y, IntPtr ptr);
public delegate void IntFuncPtr(uint handle, byte x, byte y, LogEntry info);
var callBackDelegate = new IntFuncPtr(Callback);
var callBackPtr = Marshal.GetFunctionPointerForDelegate(callBackDelegate);
InstallCallback(handle, 1, 1, callBackPtr);
Это также не сработало.
Подводя итог, я имею неуправляемый обратный вызов, который требует указателя функции на функцию, определенную как __stdcall.Если указатель на функцию не является функцией __stdcall, то стек увеличивается и переполняется.Я пытаюсь использовать обратный вызов в C # с использованием DllImport и делегата UnmanagedFunctionPointer с соглашением о вызовах stdcall.Когда я делаю это, приложение C # действует как приложение ac / c ++, которое использует функцию, отличную от __stdcall.
Как заставить это работать полностью в C #?
Edit 1:
Вот описание определения и структуры нативного метода, включая информацию о структуре C #.
extern "C" __declspec( dllexport ) short __stdcall InstallCallback(unsigned int handle, unsigned char x, unsigned char y, LOG_ENTRY info );
typedef union
{
unsigned int ul_All;
struct
{
unsigned int ul_Info:24;
unsigned int uc_IntType:8;
}t;
struct
{
unsigned int ul_Info:24;
unsigned int uc_Biu1:1;
unsigned int uc_Biu2:1;
unsigned int uc_Dma:1;
unsigned int uc_Target:1;
unsigned int uc_Cmd:1;
unsigned int uc_Biu3:1;
unsigned int uc_Biu4:1;
unsigned int res:1;
}b;
} LOG_ENTRY_C;
typedef union
{
unsigned int All;
struct
{
AiUInt32 Index:16;
AiUInt32 Res:8;
AiUInt32 IntSrc:8;
}t;
} LOG_ENTRY_D;
typedef struct log_entry
{
unsigned int a;
unsigned int b;
LOG_ENTRY_C c;
LOG_ENTRY_D d;
} LOG_ENTRY;
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct LogEntry {
public uint Lla;
public uint Llb;
public LogEntryC Llc;
public LogEntryD Lld;
}
[StructLayoutAttribute(LayoutKind.Explicit)]
public struct LogEntryC {
[FieldOffsetAttribute(0)]
public uint All;
[FieldOffsetAttribute(0)]
public LogEntryCT t;
[FieldOffsetAttribute(0)]
public LogEntryCB b;
}
[StructLayoutAttribute(LayoutKind.Explicit)]
public struct LogEntryD {
[FieldOffsetAttribute(0)]
public uint All;
[FieldOffsetAttribute(0)]
public LogEntryDT t;
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct LogEntryCT {
public uint bitvector1;
public uint IntType {
get { return ((uint)((this.bitvector1 & 255u))); }
set { this.bitvector1 = ((uint)((value | this.bitvector1))); }
}
public uint Info {
get { return ((uint)(((this.bitvector1 & 4294967040u) / 256))); }
set { this.bitvector1 = ((uint)(((value * 256) | this.bitvector1))); }
}
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct LogEntryCB {
public uint bitvector1;
public uint res {
get { return ((uint)((this.bitvector1 & 1u))); }
set { this.bitvector1 = ((uint)((value | this.bitvector1))); }
}
public uint Biu4 {
get { return ((uint)(((this.bitvector1 & 2u) / 2))); }
set { this.bitvector1 = ((uint)(((value * 2) | this.bitvector1))); }
}
public uint Biu3 {
get { return ((uint)(((this.bitvector1 & 4u) / 4))); }
set { this.bitvector1 = ((uint)(((value * 4) | this.bitvector1))); }
}
public uint Cmd {
get { return ((uint)(((this.bitvector1 & 8u) / 8))); }
set { this.bitvector1 = ((uint)(((value * 8) | this.bitvector1))); }
}
public uint Target {
get { return ((uint)(((this.bitvector1 & 16u) / 16))); }
set { this.bitvector1 = ((uint)(((value * 16) | this.bitvector1))); }
}
public uint Dma {
get { return ((uint)(((this.bitvector1 & 32u) / 32))); }
set { this.bitvector1 = ((uint)(((value * 32) | this.bitvector1))); }
}
public uint Biu2 {
get { return ((uint)(((this.bitvector1 & 64u) / 64))); }
set { this.bitvector1 = ((uint)(((value * 64) | this.bitvector1))); }
}
public uint Biu1 {
get { return ((uint)(((this.bitvector1 & 128u) / 128))); }
set { this.bitvector1 = ((uint)(((value * 128) | this.bitvector1))); }
}
public uint Info {
get { return ((uint)(((this.bitvector1 & 4294967040u) / 256))); }
set { this.bitvector1 = ((uint)(((value * 256) | this.bitvector1))); }
}
}
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct LogEntryDT {
public uint bitvector1;
public uint IntSrc {
get { return ((uint)((this.bitvector1 & 255u))); }
set { this.bitvector1 = ((uint)((value | this.bitvector1))); }
}
public uint Res {
get { return ((uint)(((this.bitvector1 & 65280u) / 256))); }
set { this.bitvector1 = ((uint)(((value * 256) | this.bitvector1))); }
}
public uint Index {
get { return ((uint)(((this.bitvector1 & 4294901760u) / 65536))); }
set { this.bitvector1 = ((uint)(((value * 65536) | this.bitvector1))); }
}
}