繁体   English   中英

将C ++结构编组到C#

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM