C#. marshaling. CallBacks. Struct.
Друзья, спасайте, есть некая dll написанная на C++, мучаюсь с подключением этой либы, мне кажется что проблема в маршализации. Я привел свой фрагмент класса обертки, верно ли я промаршализировал все переменные? Рассчитываю на ваш свежий взгляд, потому что у меня уже начались какие то танцы с бубнами.
Есть структура, в ней содержится структура с колбеками (указателями на них). Она же передается в фунцию initialize. На всякий случай привожу полны код, необходимый для работы, без абстрактных примеров.
C++ Фрагмент заголовочных файлов самой dll
typedef enum
{
MIFARE_KEY_A,
MIFARE_KEY_B
}
MifareKeyType;
typedef enum
{
OPERATION_OK,
OPERATION_ERR
}
CallbackResult;
typedef CallbackResult (*MifareAuth)(unsigned char blockNumber, MifareKeyType keyType, const unsigned char * mifareKey);
typedef CallbackResult (*MifareReadBlock)(unsigned char blockNum, unsigned char * blockData);
typedef CallbackResult (*MifareWriteBlock)(unsigned char blockNum, const unsigned char * blockData);
typedef CallbackResult (*SendAPDU)(const unsigned char * apdu, unsigned long apduLength,
unsigned char * response, unsigned long maxResponseLength, unsigned long * responseLength);
typedef struct
{
SendAPDU sendAPDU;
MifareAuth mifareAuth;
MifareReadBlock mifareReadBlock;
MifareWriteBlock mifareWriteBlock;
}
SetOfCallbacks;
COM_FTC_UTCA_LIB_EXPORT int initialize(const UContext * context);
C# Класс обертка:
class TestDLLClass
{
public TestDLLClass()
{
UContext context = new UContext();
context.callbacks = new SetOfCallbacks();
// присваиваю колбкеки, для читабельности использую лямбду
MifareAuth ma = (blockNumber, keyType, mifareKey) =>
{
Console.WriteLine("MifareAuth");
Console.WriteLine($" -blockNumber : {blockNumber} \n -keyType : {keyType} \n -mifareKey : {mifareKey}");
return CallbackResult.OPERATION_OK;
};
context.callbacks.mifareAuth = ma;
MifareReadBlock mrb = (blockNumber, blockData) =>
{
Console.WriteLine("MifareReadBlock");
return CallbackResult.OPERATION_OK;
};
context.callbacks.mifareReadBlock = mrb;
MifareWriteBlock mwb = (blockNum, blockData) =>
{
Console.WriteLine("MifareWriteBlock");
return CallbackResult.OPERATION_OK;
};
context.callbacks.mifareWriteBlock = mwb;
SendAPDU sApdu = (apdu, apduLength, response, maxResponseLength, responseLength) =>
{
Console.WriteLine("SendAPDU");
return CallbackResult.OPERATION_OK;
};
context.callbacks.sendAPDU = sApdu;
// Вот она моя самая проблемная функция
int result = initialize(ref context);
string s = result.ToString("X");
Console.ReadKey();
}
#region Функции длл
[StructLayout(LayoutKind.Sequential)]
public struct UContext
{
[MarshalAs(UnmanagedType.Struct)]
public SetOfCallbacks callbacks;
}
[StructLayout(LayoutKind.Sequential)]
public struct SetOfCallbacks
{
[MarshalAs(UnmanagedType.FunctionPtr)]
public MifareAuth mifareAuth;
[MarshalAs(UnmanagedType.FunctionPtr)]
public MifareReadBlock mifareReadBlock;
[MarshalAs(UnmanagedType.FunctionPtr)]
public MifareWriteBlock mifareWriteBlock;
[MarshalAs(UnmanagedType.FunctionPtr)]
public SendAPDU sendAPDU;
}
// typedef CallbackResult(*MifareAuth)(unsigned char blockNumber, MifareKeyType keyType, const unsigned char* mifareKey);
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public delegate CallbackResult MifareAuth(byte blockNumber, MifareKeyType keyType, IntPtr mifareKey);
//typedef CallbackResult(*MifareReadBlock)(unsigned char blockNum, unsigned char* blockData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate CallbackResult MifareReadBlock(byte blockNumber, StringBuilder blockData);
//typedef CallbackResult (*MifareWriteBlock)(unsigned char blockNum, const unsigned char * blockData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate CallbackResult MifareWriteBlock(byte blockNum, StringBuilder blockData);
//typedef CallbackResult(*SendAPDU)(const unsigned char* apdu, unsigned long apduLength, unsigned char* response, unsigned long maxResponseLength, unsigned long* responseLength);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate CallbackResult SendAPDU(StringBuilder apdu, ulong apduLength, StringBuilder response, ulong maxResponseLength, IntPtr responseLength);
//COM_FTC_UTCA_LIB_EXPORT void getUtcaVersion(char* versionString, unsigned long maxStrLength);
[DllImport(@"com_ftc_utca_lib_s.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern void getUtcaVersion(StringBuilder versionString, UInt32 maxStrLength);
//COM_FTC_UTCA_LIB_EXPORT int initialize(const UContext * context);
[DllImport(@"com_ftc_utca_lib_s.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern int initialize(/*[MarshalAs(UnmanagedType.Struct)]*/ ref UContext context);
public enum CallbackResult
{
OPERATION_OK,
OPERATION_ERR
}
public enum MifareKeyType
{
MIFARE_KEY_A,
MIFARE_KEY_B
}
#endregion
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Нужно на папку программно удалять разрешения определенного пользователяНашел пример на MSDN
Всем доброго времени сутокНесколько часов убил на то, чтобы понять, как работают потоки на C#, однако ничего толком не вышло