如何将结构传递给 C++ 函数并且 return 与某些修改相同?
How to pass a structure to a c++ function and return the same with some modifications?
我的 C++ 函数中有以下结构。
struct Cam
{
char ip[16];
char login[16];
char pass[16];
char name[16];
};
以下是我从我的cpp中暴露出来的方法class-
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);
}
我收到以下错误 -
指针和固定大小的缓冲区只能在不安全的上下文中使用
无法获取托管类型的地址、大小或声明指向托管类型的指针
你不能像你那样从函数中 return 结构,你可以简单地通过引用传递结构(顺便说一句,整个 Windows API 就是这样定义的)。
这里是声明结构体的方法,别忘了指明字符集是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 关键字。
我的 C++ 函数中有以下结构。
struct Cam
{
char ip[16];
char login[16];
char pass[16];
char name[16];
};
以下是我从我的cpp中暴露出来的方法class-
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);
}
我收到以下错误 -
指针和固定大小的缓冲区只能在不安全的上下文中使用
无法获取托管类型的地址、大小或声明指向托管类型的指针
你不能像你那样从函数中 return 结构,你可以简单地通过引用传递结构(顺便说一句,整个 Windows API 就是这样定义的)。
这里是声明结构体的方法,别忘了指明字符集是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 关键字。