Как передать структуру функции C++ и вернуть ее с некоторыми изменениями?
У меня есть следующая структура в моей функции C++.
struct Cam
{
char ip[16];
char login[16];
char pass[16];
char name[16];
};
Ниже приведен метод, который я раскрыл в своем классе cpp.
extern "C" __declspec(dllexport) Cam* AddCameraStruct1(Cam cam)
{
//modify the cam object
}
Вот как я определяю структуру и функцию в C#.
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct Cam
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string ip;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string login;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string pass;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string name;
}
[DllImport(@"mydll.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPStruct)]
internal static extern IntPtr AddCameraStruct1(DPAPI.Cam*);
Я не понимаю, как потреблять это в C#. Пожалуйста, предложите, если что-то не так.
unsafe
{
DPAPI.Cam cam = new DPAPI.Cam();
cam.ip = "192.168.0.232";
cam.login = "admin";
cam.pass = "admin";
cam.name = "kekekeke";
DPAPI.Cam* cam1 = (DPAPI.Cam*)DPAPI.AddCameraStruct1(cam);
}
Я получаю следующие ошибки -
Указатели и буферы фиксированного размера могут использоваться только в небезопасном контексте
Невозможно получить адрес, получить размер или объявить указатель на управляемый тип
1 ответ
Вы не можете возвращать структуры из функций, как вы делаете, вы можете просто передать структуру по ссылке (это то, как весь Windows API определяется BTW).
Вот как объявить структуру, не забудьте указать, что кодировка - это Ansi:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
internal struct Cam
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string ip;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string login;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string pass;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string name;
}
Вот как объявить метод (аргумент ref похож на использование *):
[DllImport(@"mydll.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void AddCameraStruct1(ref Cam pcam);
Вот как объявить это в C/C++:
extern "C" __declspec(dllexport) void AddCameraStruct1(Cam *pcam)
{
strcpy_s(pcam->name, "hello"); // for example
}
Вот как бы вы назвали это сейчас:
var cam = new Cam();
cam.ip = "192.168.0.232";
cam.login = "admin";
cam.pass = "admin";
cam.name = "kekekeke";
AddCameraStruct1(ref cam);
// cam.name is now "hello"
Обратите внимание, что вам вообще не нужно использовать ключевое слово unsafe в вашем коде.