编组c++结构到c#

本文关键字:结构 c++ 编组 | 更新日期: 2023-09-27 18:02:27

我在非托管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#结构传递给c++库时
[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

我做错了什么?

编组c++结构到c#

我从你的评论中了解了更多,

改变
__declspec(dllexport) void AddCameraStruct(Camera cam)

__declspec(dllexport) void AddCameraStruct(Cam cam)

更新:你写的:

你是对的,我错过了,IDE没有建议我什么,因为我也有相机类在c++..谢谢你:)

,我认为这是一个复制粘贴错误。在下面的例子中,它已经像这样被纠正了,它可以工作。不确定为什么/如果你的代码包含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的Output> Debug窗口中运行此项目将显示以下内容:

192.168.0.232adminkekekekeadmin

您可以看到,我将Cam结构重命名为Camera结构,假设这是您这边的剪切和粘贴错误。我还删除了printf语句,因为在调试期间看不到输出(OutputDebugString需要LPCWSTR,因此需要ATL宏A2W)。

我的猜测是,你没有显示的部分,实际上导致你的结构失败。我假设它是在c++端,因为如果结构是您键入的,它"简单地工作"(这也是通过在调试期间进入DLL函数期间将鼠标悬停在结构的字段上来"证明"的)。我建议您通过做我所做的事情来隔离问题:创建一个只处理封送和DLL导出函数原型的测试项目。