[英]Marshalling C++ struct to C#
我在非托管C ++中有这么简单的结构:
struct Cam
{
char ip[16];
char login[16];
char pass[16];
char name[16];
};
和C#编组结构:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public 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;
}
当我通过函数将C#struct传递给C ++ lib时
[DllImport("NVRLib.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void AddCameraStruct(Cam cam);
...
Cam cam = new Cam();
cam.ip = "192.168.0.232";
cam.login = "admin";
cam.pass = "admin";
cam.name = "kekekeke";
AddCameraStruct(cam);
并在C ++中打印传递的值:
__declspec(dllexport) void AddCameraStruct(Camera cam)
{
printf(cam.ip);
printf("\n");
printf(cam.login);
printf("\n");
printf(cam.name);
printf("\n");
printf(cam.pass);
strcpy(camera[CAM_NUM].ip, cam.ip);
strcpy(camera[CAM_NUM].login, cam.login);
strcpy(camera[CAM_NUM].pass, cam.pass);
strcpy(camera[CAM_NUM].name, cam.name);
CAM_NUM++;
}
它打印:
232
<EMPTY LINE>
192.168.0.232
n
我究竟做错了什么?
更新:你写道:
你是对的,我错过了,IDE没有暗示我什么,因为我确实在C ++中也有Camera类..谢谢:)
我假设是复制和粘贴错误。 在下面的示例中,它已经像这样进行了更正并且可以正常工作。 如果您的代码包含Cam
,则不确定为什么/如果您收到错误,因为它不是公认的结构(至少在我的环境中)。
底线:您展示的代码部分,工作。 您使用UnmanagedType.ByValTStr
,它取决于所选的字符集,您定义为CharSet = CharSet.Ansi
,它反过来映射到DLL库中的char *
。 这就是它应该如何编组,它是完全正确的。
我创建了一个测试应用程序PInvokeTestDll,如下所示:
DLL部分,在Win32本机DLL项目中:
#include <atlbase.h>
WIN32_DLL_UNMANGLED_API void AddCameraStruct(Camera cam)
{
USES_CONVERSION;
OutputDebugString(A2W(cam.ip));
OutputDebugString(A2W(cam.login));
OutputDebugString(A2W(cam.name));
OutputDebugString(A2W(cam.pass));
}
在头文件中:
#define WIN32_DLL_UNMANGLED_API extern "C" _declspec(dllexport)
struct Camera
{
char ip[16];
char login[16];
char pass[16];
char name[16];
};
WIN32_DLL_UNMANGLED_API void AddCameraStruct(Camera cam);
在C#项目中:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public 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;
}
class Program
{
[DllImport(@"PInvokeTestDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void AddCameraStruct(Cam cam);
static void Main(string[] args)
{
Cam cam = new Cam
{
ip = "192.168.0.232",
login = "admin",
pass = "admin",
name = "kekekeke"
};
AddCameraStruct(cam);
}
}
运行此项目在Visual Studio的“输出”>“调试”窗口中显示以下内容:
192.168.0.232adminkekekekeadmin
正如您所看到的,我将Cam
结构重命名为Camera
结构,假设您身边有剪切和粘贴错误。 我还删除了printf
语句,因为在调试期间没有看到输出(并且OutputDebugString需要LPCWSTR
,因此ATL宏A2W
)。
我的猜测是你没有显示实际导致你的结构失败的部分。 我假设它是在C ++端,因为如果结构是你键入的,它“简单地工作”(这也是通过在调试期间插入DLL函数期间悬停在结构的字段上来“证明”)。 我建议你通过做我做的事情来隔离问题:创建一个只处理编组的测试项目和DLL导出函数的原型。
在我从你的评论中学到更多东西后,
更改
__declspec(dllexport) void AddCameraStruct(Camera cam)
至
__declspec(dllexport) void AddCameraStruct(Cam cam)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.